一些筆記 — C++

戴面具的澎澎
5 min readDec 14, 2019

--

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會被呼叫到:

  1. 當object以value的方式被回傳。
  2. 當object以value的方式作為function argument。
  3. 當要以相同class的object來創建一個object的時候。
  4. 當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被呼叫的時間點有:

  1. 當一個物件是透過right value來初始化時。
  2. 當argument透過right value傳遞時。
  3. 當函數回傳物件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

--

--