1. 程式人生 > >關於c++預設的建構函式、解構函式、拷貝建構函式、move函式

關於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。例子如下:

  1. class gslice {

    public:
    gslice() = default;

    ̃gslice() = default;
    gslice(const gslice&) = default;

    };

            valarray<size_t> size;             valarray<size_t> stride;             valarray<size_t> d1;
  1. gslice(gslice&&) = default;
    gslice& operator=(const gslice&) = default;

  2. gslice& operator=(gslice&&) = default;

  3. // ...};

  4. 這段程式碼等價於:

  5. class gslice {

  6.    valarray<size_t> size;    valarray<size_t> stride;    valarray<size_t> d1;
  7. };