2014-06-09 60 views
0

爲什麼在此示例程序中未調用複製構造函數?複製構造函數不叫

input()返回一個對象的功能,複製是由物體的,但我不能看到拷貝構造函數是根據在控制檯輸出調用。

輸出:

Enter a string: ssssssssss 
ssssssssss 
Freeing s 

代碼:

#include <iostream> 
using namespace std; 

class Sample { 
    char *s; 
public: 
    Sample() { s = 0; } 
    Sample(const Sample &sample) { cout << "copyconstructor\n"; } 
    ~Sample() { if(s) delete[] s; cout << "Freeing s\n"; } 

    void show() { cout << s << "\n"; } 

    void set(char *str) { 
     s = new char[strlen(str) + 1]; 
     strcpy(s, str); 
    } 
}; 

Sample input() { 
    char instr[80]; 
    Sample str; 
    cout << "Enter a string: "; 
    cin >> instr; 
    str.set(instr); 
    return str; 
} 

int main() { 
    Sample ob = input(); 
    ob.show(); 
    return 0; 
} 
+0

http://en.wikipedia.org/wiki/Copy_elision –

+3

如果[copy ellision](http://en.wikipedia.org/wiki/Copy_elision)和[Return Value Optimization](返回值優化)不必被調用, (http://en.wikipedia.org/wiki/Return_value_optimization)。這些優化可以改變程序的可觀察行爲。你如何編譯它?你可以嘗試儘可能少的優化,但我認爲編譯器仍然可以自由地處理這種明顯的情況。其實RVO文章中的例子恰好是您的「問題」。 – luk32

+0

我也認爲這是一個組合的dupe:那些:http://stackoverflow.com/questions/3084753/copy-constructor-is-not-called,http://stackoverflow.com/questions/12686099/copy-constructor-not -calling。第一個是關於RVO的,第二個關於複製橢圓。 – luk32

回答

2

拷貝構造函數爲你的編譯器進行了優化不叫。

該優化被稱爲RVO(或NRVO),並允許編譯器在某些情況下直接在callsite處構建返回值。

大多數編譯器允許您通過選項來優化優化。鏘和gcc允許您使用轉省音的:

-fno-elide-constructors

而且你的代碼有未定義行爲的拷貝構造函數不初始化s任何東西。調用Sample::show或複製構造對象上的析構函數將導致UB,因爲未定義訪問或刪除未初始化的數據。

此外,類Sample展品UB,因爲它不遵循規則三What is The Rule of Three?)。使用隱式聲明的複製賦值操作符將執行s的淺拷貝,這可能會導致指向的數據在銷燬時被多次刪除,即UB。