2013-07-01 25 views
6

我只是創造了這樣一個類:關於構造函數和指定運營商在C++

class GreatClass 
{ 
public: 
    GreatClass(){cout<<"Default Constructor Called!\n";} 
    GreatClass(GreatClass &gc){cout<<"Copy Constructor Called!\n";} 
    GreatClass(const GreatClass &gc){cout<<"Copy Constructor (CONST) Called!\n";} 
    ~GreatClass(){cout<<"Destructor Called.\n";} 
    GreatClass& operator=(GreatClass& gc){cout<<"Assign Operator Called!";return gc;} 
    const GreatClass& operator=(const GreatClass& gc){cout<<"Assign Operator (CONST) Called!";return gc;} 
}; 

GreatClass f(GreatClass gc) 
{ 
    return gc; 
} 

,並在main()函數,有兩個版本:

版本#1:

int main() 
{ 
    GreatClass g1; 
    GreatClass G = f(g1); 
} 

版本#2:

int main() 
{ 
    GreatClass g1; 
    f(g1); 
} 

他們所有產生相同的輸出:

Default Constructor Called! 
Copy Constructor Called! 
Copy Constructor Called! 
Destructor Called. 
Destructor Called. 
Destructor Called. 

我不明白,爲什麼沒有什麼,當我分配到f(g1)發生G。此時調用的構造函數或操作符是什麼?

謝謝。

+4

複製elision是怎麼回事。如果您使用的是GCC,請嘗試使用'-fno-elide-constructors'編譯標誌。 –

+0

我想可能是你的困惑的一部分原因是'operator ='沒有被使用。這是由標準決定的。形式爲'A a2 = a1;'的東西是複製初始化,並且使用了複製構造函數(而不是賦值運算符)。複製elision也可以發揮作用。 – huskerchad

回答

13

編譯器實現允許在某些情況下刪除/刪除拷貝構造函數調用,您指定的示例是這種情況的一個很好的示例用例。不是創建一個臨時對象,然後將其複製到目標對象,而是直接在目標對象中創建對象,並將複製構造函數調用移除。

這種優化是通過Return value optimization稱爲複製省略

此外,與C++ 11 move semantics through rvalue references可能會踢,而不是複製語義。即使有移動語義,編譯器仍然可以自由應用RVO。