1. The 6 Special Member Functions
These functions are generated only when they’re called(and before any are explicitly defined by you):
- Default Constructor
- Copy Constructor
- Copy Assignment Operator
- Destructor
- Move Constructor
- Move Assignment Operator
1 | class Widget{ |
Default Constructor
- Object is created with no parameters.
- Constructor also has no parameters.
- All SMFs are public and inline function, meaning that wherever it’s used is replaced with the generated code in the function.
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, expect called when trying to set one object equal to another.
Descrutor
- Called whenever object goes out of scope.
- Cann be used for deallocating member variables and avoiding memory leaks.
2. Copy Constructors, Copy Assignment Operators
Constructor: Initializer List
We’re used to write constructors:
1 | template<typename T> |
The technique below is called an initializer list!
1 | template<typename T> |
Quick summary of initializer lists:
- Prefer to use member initializer lists, which directly constructs each member with a given value.
- Faster! Why construct, and then immediately reassign?
- What if members are a non-assginable type?
- Important clarification: you can use member initialier lists for ANY constructor, even if it has parameters.
Why aren’t the default SMFs always sufficient? Because the default compiler-generated copy constructor and copy assignment operator functions work by manually copying each member variable!
In many cases, copying is not as simple as copying each member variable! For example, in the above constructor, _elems
is a pointer, so this line makes a copy of a pointer, which means they will point to the same array.
Let’s create a new array andn copy all of the elements over.
1 | template<typename T> |
Steps to follow for an assignment operator.
- Check for self-assignment.
- Make sure to free existing members if applicable.
- Copy assign each automatically assignable member.
- Manually copy all other members.
- Return a reference to *this(that was just reassigned).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15template<typename T>
vector<T>& vector<T>::operator=(const vector<T>& other){
if(&other == this){
return *this;
}
_size = other._size;
_capacity = other._capacity;
delete[] _elems;
_elems = new T[other._capacity];
std::copy(other._elems.begin(), other._elems.begin()+other._size, _elems);
return *this;
}
3. Default and Delete
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.
1 | class PasswordManager{ |
4. Rules of 3 and 0
When should we rewrite SMFs?
Rule of 0
If the default operations work, then don’t define your own!
When the default ones generated by the compiler won’t work, most common reason is there’s a resource that our class uses that’s not stored inside of our class(e.g. dynamically allocated memory: out class only stores the pointers to arrays, not the arrays in memory itself), we should rewrite SMFs.
Rule of 3
If you explicitly define a copy constructor, copy assignment operator, or destructor, you should define all three!
What’s the rationale(理由)?
- If you’re explicitly writing your own copy operation, you’re controlling certain resources manually.
- You should then manage the creation, use and releasing of those resources.
5. Move Constructors and Move Assignment Operators
How are std::move
operations implemented in SMFs? Move constructors and move assignment operators will perform “memberwise moves”.
- Defining a copy constructor does not affect generation of a default copy assignment operator, and vice versa(反之亦然).
- Defining a move assignment operator prevents generation of a move copy constructor, and vice versa.(If the move assignment operator needs to be re-implemented, there’d likely be a problem with the move constructor).
Move operations are generated for classes only if these things are true:
- No copy operations are declared in the class.
- No move operations are declared in the class
- No destructor is declared in the class.
1 | Widget& operator=(Widget&&) = default; // support moving |
- 本文作者: 夏花
- 本文链接: http://xiahua19.github.io/2022/07/26/cs106l-11-Special-Member-Function/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!