關於c++預設的建構函式、解構函式、拷貝建構函式、move函式
在c++中,當我們定義一個類的時候,如果我們什麼都不定義的時候,c++編譯器會預設的為我們生成一些函式。
例如定義一個Example類。
class Example{
};
當我們定義一個Example類的時候,不定義任何操作的時候,c++編譯系統將為Example類生成如下預設操作函式:
1. 預設建構函式Example();
2. 拷貝建構函式Example(const Example&);
3. 拷貝賦值函式Example & operator=(const Example &);
4. 移動建構函式Example(Example &&);
5. 解構函式~Example();
預設的為程式提供這些操作,但是coder可以通過宣告這些函式中一個或幾個操作,獲取相關函式的控制權。將相關預設建構函式、拷貝建構函式、拷貝賦值函式、move構造函 數、解構函式,換成自己的定義,但是與之相關的操作(編譯器定義的)將被禁止使用。
規則如下:
1. 如果coder為類定義了建構函式,不管是拷貝建構函式還是帶引數的建構函式,則編譯器為類生成的預設建構函式將被禁止使用。
2. 如果coder為類定義了拷貝建構函式或者拷貝賦值函式、move建構函式、解構函式,則編譯器為類自動生成的拷貝建構函式、拷貝賦值函式、move建構函式、解構函式將被 禁止,也就是編譯器不在為那個類生成預設的拷貝建構函式、拷貝賦值函式、move建構函式、解構函式。但是實際上,由於向後相容的需求,即使解構函式被定義,預設的 拷貝建構函式以及預設的拷貝賦值函式也會被編譯器預設生成。
針對第一個規則,宣告一個類定義如下:
class Example{
public:
Example(int a);
private:
int a;
};
Example::Example(int a){
this->a = a;
}
在main函式中插入如下語句,Example tmp;發現編譯器報錯,說沒有建構函式。也由此證明了規則1的成立。針對規則2,宣告一個類如下:
class Example{
public:
~Example();
private:
int a;
};
Example::~Example()
{
printf("destructor"
}
在main函式中定義:
Example a, b;
a = b;
編譯通過,正確執行。
例外舉一個定義了move建構函式、不帶引數的建構函式,編譯器不會生成預設的拷貝建構函式;
class Example{
public:
Example(){}
Example(Example&& tmp);
private:
int a;
};
Example::Example(Example&& tmp)
{
printf("move");
}
Example tmp1;
Example tmp2;
tmp1 = tmp2;// 報錯,沒有copy構造
因為建構函式的相互影響,如果定義其中一個建構函式,而其他建構函式想使用預設的,則可以通過將宣告建構函式後=default。例子如下:
-
class gslice {
public:
gslice() = default;̃gslice() = default;
gslice(const gslice&) = default;};
-
gslice(gslice&&) = default;
gslice& operator=(const gslice&) = default; -
gslice& operator=(gslice&&) = default;
-
// ...};
-
這段程式碼等價於:
-
class gslice {
- valarray<size_t> size; valarray<size_t> stride; valarray<size_t> d1;
-
};