[0.x] 前言 🎓

[0.1.x] 课程相关

|

Winter 2022


- 课时:18节
- Official Course Website √(Slides为主)
- Youtube
- About CS106L (Copy from website above)
- 🌽 CS 106L is a companion class to CS106B/CS106X that explores the modern C++ language in depth. We’ll cover some of the most exciting features of C++, including modern patterns that give it beauty and power.
- 🥦 Anyone who is taking or has taken CS 106B/X (or equivalent) is welcome to enroll. In other words, we welcome anyone that has learned or is learning programming fundamentals like functions and objects/classes.
- 🥕 CS 106L is a class for 1 unit. We will be virtual for the first 3 weeks, and in-person in 420-040 afterwards. Students will complete 3 very short assignments. There are no exams or papers. All grades are S/NC. Class will finish in week 9 to give you time for finals.
- 🏢 CS 106L is built for you! Even if you’re not taking the class, you’re welcome to come to our office hours, in-person after week 2 on Tuesdays and Thursdays from 4:45-5:45pm in 380-380C. If you don’t feel comfortable coming in-person, we’ll have virtual office hours (times TBD).
- Other Reference
- github/PKUFlyingPig/CS106L
- Other Helpful Tools
- https://gcc.godbolt.org/
| | —- |

[0.2.x] 学习日志

GuestL
123
456
789
012
345
678
【2022】
[1.13] 知难而退😜
[2.5] Guest Lecture
[2.6] 整理 L1 L3
[2.7] 整理 L2 L3 L4
[2.8] L5 L6 L7
[2.10] L8 L9 L10
[2.11] L11 L12
[2.16] L13
[2.17] L14

[0.3.x] 笔记结构

| > 106L的课程和OOP课程内容有重复的地方我将不再详细记录,所以只会记录我认为有必要记录的地方。

本笔记主要依据Slides自学记录。

| | —- |


[1.x] 课程笔记 📖

Guest Lecture: Meta-function

| > 该章节来自油管视频

元函数meta-function
- 元函数本质上不是函数,而是结构体模版的静态成员访问
- 利用元函数,可以实现 type/valuetype/value 的映射(函数只能实现 valuevalue 的映射)
```cpp // meta-function template < typename T , int V > struct my_metaFun{ // It’s an alias. using type = T; // We don’t want to create any instance of the struct template, so static is ideal. static const int value = V; }; // use // my_metaFun< aType , aValue >::type // & // my_metaFun< aType , aValue >::value

  1. <br />- 这个元函数实现了输入一个类型和一个整数,你可以使用`my_metaFun< aType , aValue >::type`和`my_metaFun< aType , aValue >::value`来获取类型/值<br /><br /><br /> - `using`和`typedef`的区别<br />
  2. 定义模板别名时,只能用`using`,其他时候两者相同。<br /><br />元函数的概念基本如此,但到目前为止元函数的功能还非常有限。因为我们不在任何函数中,所以我们不能使用类似于循环、条件分支之类的操作。所以我们需要利用一个特性来实现某些功能。<br /><br />**模板演绎Template Deduction **[44:00]<br />- **模板特化template specialization**<br />```cpp
  3. template < typename T > // generic
  4. class vector{
  5. // implementation using an array
  6. // that is resized as necessary
  7. };
  8. template <> // specialized
  9. class vector<bool> {
  10. // implementation using a bit arry
  11. // so each element takes one bit
  12. };


- 下面那个模板和上面那个模板相比,更加特化
- 代码内使用模板时,编译器会按照特化程度从大到小的顺序逐一尝试套用同一内容的不同模板,直到找到为止
- 如果没有发现任何可以套用的模板,或者出现歧义,则会报错
> All the template rules, summarized.

  • Compiler will rank all the templates, try each until it finds one that works.
  • Error only if none work or if there is a tie.

利用模板特化从特化程度大到特化程度小的特性,我们可以构造同一元函数的多个特化,从而实现条件分支。```cpp template < typename T, typename U > struct is_same { static const bool value = false; };

template < typename T > struct is_same { static const bool value = true; };

// bool diff = is_same::value; // bool same = is_same::value;

  1. ```cpp
  2. template < typename T >
  3. struct remove_const{
  4. using type = T;
  5. };
  6. template < typename T >
  7. struct remove_const <const T>{
  8. using type = T;
  9. };
  10. // using IntToInt = remove_const<int>::type;
  11. // using ConstIntToInt = remove_const<const int>::type;

在编译时刻去掉不必要的代码
- constexpr(C++11)关键字修饰的内容,如果在编译时刻可以被计算,那么就会在编译时刻被计算(const只保证在运行时刻其值不被修改)
- 使用if constexpr(c++17),在编译时就只会保留符合条件的那一部分。
> if constexpr : You can calculate the boolean at compile-time. Replace the entire if/else with the code that will actually be run.

  1. if constexpr(flag){
  2. // A
  3. } else {
  4. // B
  5. }
  6. // If `flag` is affirmatory, than only one of A&B will be compiled.

Key Takeaways

  • Templates allow you to treat types as “variables”.
  • Meta-funcions lets you modify these types, or to query information about these template types.
  • (if) constexpr gives you the flexibility to modify the source code based on the template type.
  • These allow you to optimize code based on type!

image.png | | —- |

Lecture 1: Welcome!

| > 该章节来自课程页面Slides

| | —- |

Lecture 2: Types and Structs


- struct
- pair:一个STL内置的结构体
- 可以利用pair使一个函数同时返回状态信息和结果
- 注意避免实例化返回值,使用make_pair(statusCode,returnResult);更好
- Type Deduction with auto
- The type is deduced by the compiler.
- 定义变量时使用auto可以让编译器自动推理该变量的类型
- auto a = 1;int
- auto ch = 'q'char
- **auto s = "qaq"****char***

Lecture 3: Streams

| Stream
- An abstraction for input/output.
- Streams convert between data and the string representation of data.


Output Streams ostream
- coutis an output stream that has type ostream.
- cout是一个<iostream>里的全局常量,它输出到console
- 使用<<将数据传入ostream
- 它会将任何数据转化为字符串形式并将其传入流
Output File Streams ofstream
- 使用<<将数据传入ofstream
- 它会将任何数据转化为字符串形式并将其传入文件
- 使用ofstream之前需要初始化你的ofstream对象,使其与目标文件链接
- std::ofstream ots("out.txt",std::ofstream::out);
> To use any other(except cout) output stream, you must first initialize it!



Input Streams istream
- cinis an input stream that has type istream.
- cin是一个<iostream>里的全局常量,它从console中接收输入
- 使用>>将数据从istream中解析出来
- 它会将流中的字符串解析为数据
- Buffer
- cin可以用来解析单个词或者数据
- 如果要解析一整行内容,使用 std::getline(istream &stream, string &line);
> Don’t mix **>>** with **getline**!

  • >> reads up to the next whitespace character and does not go past that whitespace character.
  • getline reads up to the next delimiter(by default, ‘\n’), and does go past that delimiter.
  • Don’t mix the two or bad things will happen!

Input File Streams ifstream
- 使用>>将数据传入ifstream
- 它会将文件流中的字符串解析为数据
- 使用ifstream之前需要初始化你的ifstream对象,使其与目标文件链接
- std::ifstream ins("in.txt",std::ofstream::in);
> To use any other(except cin) input stream, you must first initialize it!



Stringstreams stringstream
- #include <sstream>
> - Input stream: istringstream

  • Give any data type to the istringstream, it’ll store it as a string!
    • Output stream: ostringstream
  • Make an ostringstream out of a string, read from it word/type by word/type!
    • The same as the other i/ostreams you’ve seen!
  1. // ostringstream
  2. string judgementCall(int age, string name, bool lovesCpp){
  3. std::ostringstream formatter;
  4. formatter << name <<", age " << age;
  5. if(lovesCpp) formatter << ", rocks.";
  6. else formatter << " could be better";
  7. return formatter.str();
  8. }
  9. // ---------------------------------------------------------------------
  10. ostringstream oss("qwq"); // 这时<<写入东西会从头开始写,逐字覆盖
  11. ostringstream oss("qwq",ostringstream::ate); // 这时<<写入会从末尾追加
  1. // istringstream
  2. Student reverseJudgementCall(string judgement){
  3. std::istringstream converter;
  4. string fluff;
  5. int age;
  6. bool lovesCpp;
  7. string name , cool;
  8. converter >> name >> fluff >> age >> fluff >> cool;
  9. if(fluff == "rocks") return Student{name, age, "bliss"};
  10. else return Student{name, age, "misery"};
  11. }

| | —- |

Lecture 4: Initialization and References

| Initialization of vectors
- vector<int> v1(3,5);(3个5) = vector<int> v1{5,5,5};(C++11)
> Uniform initialization: curly bracket initialization. Available for all types, immediate initialization on declaration!

(C++11)可以用{}对所有类型进行初始化。```cpp std::vector vec{1,3,5}; std::pair numSuffix1{1,”st”}; Student s{“Frankie”, “MN”, 21}; // struct int x{5}; string f{“Frankie”};

  1. <br />- `auto`<br />
  2. **Structured Binding(C++17)**```cpp
  3. // Common struct is also acceptable.
  4. auto p = std::make_pair("s", 5);
  5. auto [a, b] = p;
  6. // than
  7. // a = "s";
  8. // b = 5;

References> An alias(another name) for a named variable.

  • 参考
    ```cpp // 使用for/auto时如何正确修改被循环内容 void shift(vector>& nums) { for (auto &[num1, num2] : nums) {
    1. num1++;
    2. num2++;
    } } `` ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22387144/1644228942619-9ea7be17-7436-4d81-a749-e44f67df5c60.png#clientId=u7e97006a-43c7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=334&id=u46468d78&margin=%5Bobject%20Object%5D&name=image.png&originHeight=417&originWidth=887&originalType=binary&ratio=1&rotation=0&showTitle=false&size=87539&status=done&style=shadow&taskId=ued8b1cbd-c7e4-4b8d-bdee-8d80950c246&title=&width=709.6)<br />-const` & reference
    | | —- |

Lecture 5: Containers

| Sequence Containers
- Simple
- vector``deque``list``tuple``array``string
image.png> std::vector: use for almost everything

std::deque: use if you are frequently inserting/removing at front std::list: use very rarely, and only if you need to split/join multiple lists

  • Adaptors(在顺序容器的基础上定义了新的借口)
    - stack``queue``priority_queue
    - 封装wrapper
    > Container adaptors provide a different interface for sequence containers.

    You can choose what the underlying container is!

Associative Containers
- Ordered
- set``map
- Unordered
- unordered_set``unordered_map(faster)
- 对于有序容器,需要提供比较运算符的定义;对于无序容器,则需要提供哈希函数
| | —- |

Lecture 6: Iterators and Pointers

| Iterators> A way to access all containers programmatically!

image.png
- Random access iterators support indexing by integers!
```cpp // only random access iterators it += 3; it -= 70; auto elem = it[5];

  1. <br />- **for-each loop**<br />```cpp
  2. std::set<int> set{3, 1, 4, 1, 5, 9};
  3. for (const auto &elem : set) {
  4. cout << elem << endl;
  5. }
  6. std::map<int> map{{1, 6}, {1, 8}, {0, 3}, {3, 9}};
  7. for (const auto &[key, value] : map) {
  8. cout << key << ":" << value << ", " << endl;
  9. }

Pointers> One of the main strengths of C++: accessing objects by address!

Iterators vs. Pointers> • Iterators are a form of pointers!

• Pointers are more generic iterators. • Pointers can point to any object, not just elements in a container!

| | —- |

Lecture 7: Classes

| Classes> A programmerdefined custom type. An abstraction of an object or data type.

Issues with struct
- Public access to all internal state data by default.
- Users of struct need to explicitly initialize each data member.
> “A struct simply feels like an open pile of bits with very little in the way of encapsulation or functionality. A class feels like a living and responsible member of society with intelligent services, a strong encapsulation barrier, and a well defined interface.”

—— Bjarne Stroustr

Classes provide their users with a public interface and separate this from a private implementation.

  • head file & .cpp file
    - Always declare things in the .h and implement in the .cpp!
    - this
    - C’tor & D’tor
    namespaces
    Object> Objects are instances of classes.

    Objects encapsulate data related to a single entity.

    • Define complex behavior to work with or process that data:

    Student.printErollmentRecord(),vector.insert() Objects store private state through instance variables: Person::name,Vehicle::ownerName Expose private state to other through public instance methods: Person::getName(),Vehicle::changeOwnerName(string name)

    • Allow us to expose state in a way we can control.

    | | —- |

Lecture 8: Template Classes and Const Correctness

| Template Class> - A class that is parametrized over some number of types.

  • A class that is comprised of member variables of a general type/types.

Fundamental Theorem of Software Engineering: Any problem can be solved by adding enough layers of indirection.

  1. // syntax
  2. template <typename T>
  3. class className {
  4. public:
  5. /*...*/
  6. private:
  7. /*...*/
  8. };

Member Types
std::vector::iterator it = a.begin();
- iterator is a member type of vector
<有关这部分内容,并没有非常理解,所以可能存在比较明显的错误,请dalao用力教育我!>
使用类模板的成员类型时,由于在compile-time无法得知使用的到底是成员类型还是其他的什么,所以需要在前面加上typename来表示你使用的是一个成员类型而非一个成员变量。
- 可以参考这个视频
在定义函数时,请参考以下内容```cpp // right template typename vector::iterator vector::insert(iterator pos, int value) { // … }

// wrong template vector::iterator vector::insert(iterator pos, int value) { // … }

  1. > Used to make sure your clients have a standardized way to access important types.
  2. > Lives in your namespace: vector::iterator.
  3. > After class specifier, you can use the alias directly (e.g. inside function arguments, inside function body).
  4. > Before class specifier, use typename.
  5. **当你在**`**.h**`**中使用了模板,并在**`**.cpp**`**中定义了实际代码,请在**`**.h**`**中**`**#include "xxx.cpp"**`**,否则将无法通过编译。**(因为模板在实例化之前并不产生实际代码)> Templates don't emit code until instantiated, so include the `.cpp` in the `.h` instead of the other way around!
  6. <br /><br />**Const**> - Keyword indicating a variable, function or parameter can't be modified.
  7. **const-interface**> - All member functions marked const in a class definition.
  8. > - Objects of type const ClassName may only use the const-interface.
  9. `size_t size() const{}` / `size_t size() const;`<br /><br />为`const_begin()`/`const_end()`设置`const_iterator`可以提供只读的访问 |
  10. | --- |
  11. <a name="c0YYS"></a>
  12. ## Lecture 9: Template Functions
  13. | **Generic Programming**> Writing reusable, unique code with no duplication!
  14. _**Using template!**_```cpp
  15. template <typename Type = int> // default typename
  16. Type myMin(Type a, Type b) {
  17. return a < b ? a : b;
  18. }
  19. // call : myMin<int>(2,3);

Template Metaprogramming (TMP)> Writing code that runs during compilation (instead of run time).

  • Make compiled code packages smaller.
  • Speed up code when it’s actually running.

[元函数]```cpp template struct Factorial { enum { value = n * Factorial::value }; }; template<> // template class “specialization” struct Factorial<0> { enum { value = 1 }; }; std::cout << Factorial<10>::value << endl; // prints 3628800, but run during compile time!

  1. > TMP was actually discovered (not invented, discovered) recently!
  2. > Where can TMP be applied?
  3. > - Ensuring dimensional unit correctness.
  4. > - Optimizing matrix operations.
  5. > - Generating custom design pattern implementation.
  6. > - policy-based design (templates generating their own templates.
  7. |
  8. | --- |
  9. <a name="MYGGr"></a>
  10. ## Lecture 10: Functions and Lambdas
  11. | **Function Pointers**> **Predicate Functions**
  12. > - Any function that returns a boolean is a predicate!
  13. ```cpp
  14. bool cmp(int x,int y){
  15. return x < y;
  16. }
  17. int main(){
  18. int a[1000], n = 10;
  19. // ...
  20. std::sort(a+1,a+n+1,cmp); // "cmp" here is a function pointer.
  21. // It can be treated like a virable.
  22. // ...
  23. return 0;
  24. }


Lambdas> Inline functions that can know about other variables.

Lambda表达式有三种形式:
- [ CaptureList ]( ParamsList ) -> ReturnType { FunctionBody }
- [ CaptureList ]( ParamsList ){ FunctionBody }
- [ CaptureList ]{ FunctionBody }
其中:
1. CaptureList指捕获的外部变量列表
- Lambdas默认无法访问外部变量,除非在方括号中指明
- 显示捕获:
- 直接写入变量名[x]表示捕获:只读
- 写入引用[&x]表示引用捕获:读写
- 隐式捕获:
- [=]捕获所有外部变量:只读
- [&]引用捕获所有外部变量:读写
- 多参数:
- 多参数可以通过,隔开,但隐式捕获(如果存在)需要放在第一位,往后的显示捕获变量规则将覆盖隐式捕获
- eg:[&,limit]表示limit捕获,其他按引用捕获
- eg:[&limit1,limit2]表示limit1引用捕获,limit2捕获
- eg:[limit,=]报错(即使他们都表示按值捕获)
- 支持捕获this,但this对应=,使用[=,*this]则不报错
2. ParamsList指该函数的传入参数
- 在lambdas表达式中,掺入参数可以使用auto类型
- 不支持默认值default value
- 所有参数必须有参数名
- 其余与正常函数一样
3. ReturnType指该函数的返回值类型
- 与正常函数一样
4. FunctionBody指函数本体
- 与正常函数一样
5. 如果写成[]()mutable -> int {},则可以在 FunctionBody 内修改捕获的变量
一般而言,lambdas函数都是当做匿名函数使用,但你也可以auto myFun = [](){};> Lambdas are cheap, but copying them may not be.

Use lambdas when you need a short function, or one with read/write access to local variables! Use function pointers for longer logic and for overloading. We use “auto” because type is figured out in compile time.

Functors and Closures> A functor is any class that provides an implementation of operator().

Lambdas are essentially syntactic sugar for creating a functor. If lambdas are functor classes, then “closures” are instances of those classes. At runtime, closures are generated as instances of lambda classes.

| | —- |

Lecture 11: Midquarter Review



复习课

Lecture 12: Operators

| Function Overloading
Operator Overloading
Two ways to overload operators:
1. member functions
- You should only define the rhs of the operators while the lhs is always this
- Operators can only be called on the left hand side.
2. non-member functions
- You should define both lhs and rhs.
- The STL prefers using non-member functions for operator overloading:
1. Allows the LHS to be a non-class type. (e.g. double < Fraction)
1. Allows us to overload operations with a LHS class that we don’t own!
- Use friend to access the private members.
Rules of Operator Overloading(To make your codes more friendly.)> 1. Meaning should be obvious when you see it.

  1. Should be reasonably similar to corresponding arithmetic operations.
    • For instance, don’t define + to mean set subtraction!
  2. When the meaning isn’t obvious, give it a normal name instead.

| | —- |

Lecture 13: Special Member Functions(SMFs)

| SMFs
- Default Constructor
- Object is created with no parameters.(C’tor has no parameters as well.)
- Copy Constructor
- Another type of constructor that creates an instance of a class.
- Constructs a member-wise copy of an object (deep copy).
- Copy Assignment Operator
- Very similar to copy constructor, except called when trying to set one object equal to another.
- eg. w1 = w2;
- Destructor
- Autoly called whenever object goes out of scope.
- Can be used for deallocating member variables and avoiding memory leaks.
- Move Constructor
- Allow for moving objects and std::move operations (rvalue refs).
- Move Assignment Operator
```cpp class Widget { public: Widget(); // default constructor Widget (const Widget& w); // copy constructor Widget& operator = (const Widget& w); // copy assignment operator ~Widget(); // destructor Widget (Widget&& rhs); // move constructor Widget& operator = (Widget&& rhs); // move assignment operator };

  1. > - These functions are generated only when they're called.
  2. > - All SMFs are public and inline function, meaning that wherever it's used is replaced with the generated code in the function.
  3. <br /><br />**initializer list**> - Prefer to use member initializer lists, which directly constructs each member with a given value.
  4. > - Faster! Why construct, and then immediately reassign?
  5. > - What if members are a non-assignable type (you'll see by the end of lecture how this can be possible!)
  6. > - Important clarification: you can use member initializer lists for ANY constructor, even if it has parameters (and thus isn't an SMF)
  7. Default compiler-generated copy constructor will cause error while there are pointers members for that default compiler-generated always just simply copy members variables.```cpp
  8. template <typename T>
  9. vector<T>::vector<T>(const vector::vector<T>& other):
  10. _size(other._size),
  11. _capacity(other._capacity),
  12. _elems(new T[other._capacity]) {
  13. std::copy(other._elems, other._elems + other._size, _elems);
  14. }

Summary: Steps to follow for an assignment operator

  1. Check for self-assignment.
  2. Make sure to free existing members if applicable.(Because this option can be called more than once.)
  3. Copy assign each automatically assignable member.
  4. Manually copy all other members.
  5. Return a reference to *this (that was just reassigned).

image.png
**= delete** & **= default**
- Manipulating SMFs when you write your own functions
- Adding = delete; after a function prototype tells C++ to not generate the corresponding SMF.
- Adding = default; after a function prototype tells C++ to still generate the default SMF, even if you’re defining other SMFs.(That means, default C’tor won’t be generated while there has other C’tor but has no =default;)
```cpp class PasswordManager { public: PasswordManager(); PasswordManager(const PasswordManager& pm) = default; ~PasswordManager(); // other methods … PasswordManager(const PasswordManager& rhs) = delete; PasswordManager& operator = (const PasswordManager& rhs) = delete; private: // other important members … }

  1. > When should you define your own SMFs?
  2. > - When the default ones generated by the compiler won't work.
  3. > - Most common reason: there's a resource that our class uses that's not stored inside of our class.
  4. > - e.g. dynamically allocated memory
  5. > - our class only stores the pointers to arrays, not the arrays in memory itself!
  6. > - If you explicitly define a copy constructor, copy assignment operator, or destructor, you should define all three!
  7. > - What's the rationale?
  8. > - If you're explicitly writing your own copy operation, you're controlling certain resources manually.
  9. > - You should then manage the creation, use, and releasing of those resources!
  10. > [TODO]Move Operations
  11. > - Move constructors and move assignment operators will perform "memberwise moves".
  12. > - Defining a copy constructor does not affect generation of a default copy assignment operator, and vice versa.
  13. > - Defining a move assignment operator prevents generation of a move copy constructor, and vice versa.
  14. > - Rationale: if the move assignment operator needs to be re-implemented, there'd likely be a problem with the move constructor.
  15. > Some nuances to move operation SMFs
  16. > - Move operations are generated for classes only if these things are true:
  17. > - No copy operations are declared in the class
  18. > - No move operations are declared in the class
  19. > - No destructor is declared in the class
  20. > - Can get around all of these by using default:
  21. ```cpp
  22. Widget(Widget&&) = default;
  23. Widget& operator=(Widget&&) = default; // support moving
  24. Widget(const Widget&) = default;
  25. Widget& operator=(const Widget&) = default; // support copyin

| | —- |

Lecture 14: Move Semantics

| l-values & r-values
l-values
- can appear on the left or right of =
- have name
- not temporary : live until the end of scope(normally)
```cpp int x = 3; int y = x; // x is a l-value

  1. **r-values**<br />- can ONLY appear on the right of `=`<br />- don't have name<br />- temporary : live until the end of line(normally)<br />```cpp
  2. int x = 3;
  3. // 3 is a r-value

eg
image.png
- You can only reference l-values with &, while you can only reference r-values with &&.
image.png
- When the item on the right of the = is an r-value we should use move assignment.
- R-values are always about to die, so we can steal their resources.
image.png
- So we should use & and && to overload =.
```cpp int main() { int x = 1; change(x); //this will call version 2 change(7); //this will call version 1 } void change(int&& num){…} //version 1 takes r-values void change(int& num){…} //version 2 takes l-values //num is a reference to vec

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/22387144/1645078267235-c33639ce-c7f6-4db9-abf1-ad4632fd5b82.png#clientId=u6cff8d99-06f1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=453&id=u4d47ea72&name=image.png&originHeight=566&originWidth=1118&originalType=binary&ratio=1&rotation=0&showTitle=true&size=113492&status=done&style=shadow&taskId=u6d355eb8-a84b-4602-936a-7443678376b&title=%22steal%22%20the%20resources&width=894.4 ""steal" the resources")<br />- After that, compiler will autoly pick the `=` based on whether the **RHS **is a **l-value** or a **r-value**. <br /><br /><br />- We can use `std::move()` to make it better.<br />- If we don't use, it actually acts as a copy assignment.<br />- However, if we use `std::move()` to froce it to be a **r-value**, we can still its value that will preform better.<br />```cpp
  2. vector<T>& operator=(vector<T>&& other) {
  3. if (&other == this) return *this;
  4. _size = std::move(other._size);
  5. _capacity = std::move(other._capacity);
  6. //we can steal the array
  7. delete[] _elems;
  8. _elems = std::move(other._elems);
  9. return *this;
  10. }

Where else should we use std::move? Wherever we take in a const & parameter in a class member function and assign it to something else in our function.

After a variable is moved via std::move, it should never be used until it is reassigned to a new variable!

Don’t use std::move outside of class definitions, never use it in application code!

[

](https://www.youtube.com/watch?v=IOkgBrXCtfo)
- Read these for better understanding:
- github仓库
- 油管视频
| | —- |