2012-06-29 111 views
1

可能重複:
Why copy constructor is not called in this case?複製構造函數沒有調用,爲什麼?

我有以下代碼:

#include <iostream> 
#include <new> 

using namespace std; 

class test { 
    int *p; 
public: 
    test operator=(test a); 
    test() { 
     p = new int [2]; 
     cout <<"Default Constructor was done here." << "\n"; 
    } 

    test(const test &a) { 
     p = new int [2]; 
     this->p[0] = a.p[0]; 
     this->p[1] = a.p[1]; 
     cout << "Copy Constructor was done here." << "\n"; 
    } 

    ~test() { 
     delete p; 
     cout << "Destructor was done here." << "\n"; 
    } 
    int set (int a, int b) { 
     p[0] = a; 
     p[1] = b; 
     return 1; 
    } 

    int show() { 
     cout << p[0] << " " << p[1] << "\n"; 
     return 2; 
    } 
};  

test test::operator=(test a) { 
    p[0] = a.p[0]; 
    p[1] = a.p[1]; 
    cout << "Operator = was done here" << "\n"; 
    return *this; 
} 

test f(test x) { 
    x.set(100, 100); 
    return x; 
} 

int main() { 
    test first; 
    test second; 
    first.set(12, 12); 

    //f(first); 
    //second = first; 
    second = f(first); 


    first.show(); 
    second.show(); 

    getchar(); 
    return 0; 
} 

拷貝構造函數被調用只有三次?爲什麼? 如果我理解,我們做了四個副本(我們發送對象到func,func返回值,我們發送對象給operator =,operator =返回值)。

+6

複製elision,大量重複... –

回答

3

這可能是copy elision的影響。編譯器可以自由地避免將對象複製到不影響程序的任何地方。複製構造函數/析構函數的副作用不會影響本案例中的程序。一般來說,它會避免複製一個臨時的用作函數參數,因爲臨時會在之後被銷燬。

這可以在§12.8.32在標準中找到:

當滿足特定條件時,一種實現被允許省略 一個類對象的複製/移動結構,即使複製/移動 構造函數和/或析構函數具有副作用。在這種情況下,實施將對複製/移動操作省略的源和目標作爲簡單的兩種不同的方式來引用同一對象,並且銷燬該對象發生在兩個時間的較晚的時間,其中兩個如果沒有進行優化,對象就會被銷燬。一份,省音/移動 操作,稱爲copyelision,在下面的 情況下才允許(這可能合併,以消除多個副本):

    return語句中
  • 與類返回類型的功能,當表達式是一個非易失性自動物體相
    相同CV-unquali音響ED類型作爲函數返回類型名稱,
    複製/移動操作可以通過直接構建自動
    物體插入函數的返回值
  • 被省略
  • in throw-exp當操作數是非範圍的自動對象的名稱,其作用域的範圍不超出 內部封閉嘗試塊的末尾(如果有的話), 從操作數到異常的複製/移動操作對象(15.1) 可以通過直接構建自動物體插入 異常對象
  • 當尚未結合至參考(12.2)臨時類對象會becopied可以省略/移動到一個類對象witht他 相同cv-unquali fi ed型,複製/移動操作可以省略 直接構造臨時對象到目標中
    省略複製/移動
  • 當異常處理程序的異常聲明(條款15)聲明異常對象(15。)的同一類型的對象(cv-限定除外)爲
    。1)中,複製/移動操作可以省略
    bytreatingthe異常聲明作爲例外
    對象的別名,如果程序的含義將是除了 執行構造和析構爲對象通過
    聲明不變 異常聲明。

在這種情況下,它可能會簡單地使用由f作爲輸入返回的對象爲operator=,因爲它是一個臨時的,因此將右後反正被破壞。

+0

輸出不可觀察的行爲? – BoBTFish

+3

編譯器即使有副作用也可以刪除副本。 – jrok

+2

@BoBTFish它是,但答案是錯的。 「編譯器可以自由避免將對象拷貝到不影響程序的任何地方」 - 這部分是不正確的。 –

相關問題