Default Constructor
Default constructor沒有argument。當programmer沒有給的時候,compiler會視情況自動定義default constructor成class中的inline public member。
class A {public: A () {}; // 沒有做任何initialization A () {
x = 10;
}private: int x;
}
Compiler會視情況定義default constructor (without body)。
class A {public: int x;
A (int x = 1): x(x) {}; // programmer定義的constructor}class B: A{
}B b;// 其中B沒有定義任何constructor,當B被創建的時候,compiler會自動定義constructor。而且A的constructor也會被呼叫class C {public: A a;
}C c;// C的constructor會implicitly defined,接著呼叫A的constructor。class D { D (int y) : A(y) {}}D d; // compile error: 因為沒有對應的constructor。// 此時D的default constructor不會被implicitly defined,因為D裡面有定義一個constructor。
Copy Constructor
Copy constructor是一個member function用來initialize 相同class的object。
通常寫法如下:
ClassName(const ClassName& rhs);
使用時機像是當要透過一個相同class物件創建新的物件會呼叫到copy constructor。
class Point {
public:
// Default constructor Point (int x, int y) _x(x), _y(y) {}
// Copy constructor Point (const Point& rhs) {
_x = rhs._x;
_y = rhs._y; }private:
int _x;
int _y;}...
Point p1(10, 50); // 這裡是default constructor
Point p2 = p1; // 這裡則會呼叫copy constructor
Point p3;
p3 = p1; // 但這裡是assignment operator
Copy constructor會在複製一個object的內容到新宣告的object裡面的時候使用。所以要注意的是在這種情況下,如果有增添或刪減要被複製的成員變數,copy constructor也要做相對應的修改。
在以下情況copy constructor會被呼叫到:
- 當object以value的方式被回傳。
- 當object以value的方式作為function argument。
- 當要以相同class的object來創建一個object的時候。
- 當compiler需要產生temporary object的時候。
但不保證每個狀況都會被呼叫到。compiler會優化整個copy的過程。see return value optimization: https://en.wikipedia.org/wiki/Copy_elision#Return_value_optimization
Move Constructor
Move constructor是C++ 11中move semantics的特色。當一個constructor中的第一個parameter是T&&, const T&&時即為move constructor。
move constructor被呼叫的時間點有:
- 當一個物件是透過right value來初始化時。
- 當argument透過right value傳遞時。
- 當函數回傳物件a時,a有move constructor。
// 1.
T a = std::move(b);// 2.
void f(T t) { ... };
f(std::move(a))// 3.
T f() {
return a; // a has a move constructor}
Move constructor會將argument中真實的resources (allocated memory)轉移走,讓原本的argument變成一個valid的intermediate state。舉例來說,從std::string move到std::vector,會讓string變成空字串。
另外當有destructor的時候,就會防止implicit move constructor。
class C { ~C () {}}C c2 = std::move(c1); // This will failed to call move constructor. Call copy constructor instead.
但如果加了default則可以強制呼叫move constructor。
class D { ~D () {} D(D&& d) = default;
}
例子:
class A { int x;
string y;
A (const A& o) : x(o.x), y(o.y) {} // copy constructor
A (A&& o) noexcept : x(std::move(o.s)), y(std::exchange(o.y, 0)) {}}A f(A a) { return a; }A a1 = f(A()); // function回傳時會用move constructor
A a2 = std::move(a1); // move之後,a1的x, y都會變成zero value