2010-12-19 45 views
2

隨着下面的程序,我試圖用copy ctor進行試驗,有一點不清楚,當函數f()返回時應該使用copy-ctor爲h2創建一個新對象,但是我猜這是通過臨時對象完成的,該對象使用對象的構造器然後進行復制,但是銷燬輸出顯示我在這個推理上是錯誤的...對此問題有一些澄清...)臨時和複製構造函數

#include <fstream> 
#include <string> 
using namespace std; 
ofstream out("HowMany2.out"); 

class HowMany2 { 
    string name; // Object identifier 
    static int objectCount; 
public: 
    HowMany2(const string& id = "") : name(id) { 
    ++objectCount; 
    print("HowMany2()"); 
    } 
    ~HowMany2() { 
    --objectCount; 
    print("~HowMany2()"); 
    } 
    // The copy-constructor: 
    HowMany2(const HowMany2& h) : name(h.name) { 
    name += " copy"; 
    ++objectCount; 
    print("HowMany2(const HowMany2&)"); 
    } 
    void print(const string& msg = "") const { 
    if(msg.size() != 0) 
     out << msg << endl; 
    out << '\t' << name << ": " 
     << "objectCount = " 
     << objectCount << endl; 
    } 
}; 

int HowMany2::objectCount = 0; 

// Pass and return BY VALUE: 
HowMany2 f(HowMany2 x) { 
    x.print("x argument inside f()"); 
    out << "Returning from f()" << endl; 
    return x; 
} 

int main() { 
    HowMany2 h("h"); 
    out << "Entering f()" << endl; 
    HowMany2 h2 = f(h); 
} 

輸出

HowMany2() 
    h: objectCount = 1 
Entering f() 
HowMany2(const HowMany2&) 
    h copy: objectCount = 2 
x argument inside f() 
    h copy: objectCount = 2 
Returning from f() 
HowMany2(const HowMany2&) 
    h copy copy: objectCount = 3 
~HowMany2() 
    h copy: objectCount = 2 // Confused here !!!! why not h copy copy 
~HowMany2() 
    h copy copy: objectCount = 1 
~HowMany2() 
    h: objectCount = 0 

回答

2

h copy copy基本上h2從這一行:

HowMany2 h2 = f(h); 

它的破壞,當你退出main

h copyf的參數,它在f返回時被破壞。由於fmain之前返回,因此h copyh copy copy之前遭到破壞。

請注意,RVO(返回值優化)是由編譯器完成的。此代碼中沒有創建臨時對象。實際上,這個代碼可能會根據編譯器輸出不同的結果。編譯器可以自由地在這段代碼中進行1或2次拷貝構造函數的調用。 (也許零也正是在這種情況下有可能,我不知道該怎麼雖然證明它。)

編輯:

void f(HowMany2 *result, HowMany2* xptr) { 
    HowMany2 x(*xptr); // local copy 

    x.print("x argument inside f()"); 
    out << "Returning from f()" << endl; 

    new(result) HowMany2(x); // copy the return value 

    x.~HowMany(); // destroy local copy 
} 

int main() { 
    HowMany2 h("h"); 
    out << "Entering f()" << endl; 
    HowMany2 h2; // not initialized 
    f(&h2, &h); 
    h2.~HowMany2(); 
} 
+0

Thx爲澄清,比這個代碼字符串有什麼不同a =「a」;編譯器通過調用帶有c風格字符串的字符串構造函數創建一個臨時文件,並使用Ctl初始化一個臨時拷貝來複制C++初始化第13章,這是提問時的推理,但不同的實現可以做代碼中的不同事物... – 2010-12-19 18:26:16

1

:您的代碼是這樣的(僞代碼)編譯器實現在那個「混亂」的地方,函數f的臨時局部對象被銷燬(「h copy」),在函數外部創建副本(「h copy copy」)後被複制。然後,函數外部的對象按其創建的相反順序被銷燬:被複制的對象(「h copy copy」)和最後的原始對象(「h」)。

0

來自f()的返回值正在將一個副本構造返回到main。
結果將該值存入變量h2

因此函數中的參數x首先被銷燬(因爲它離開函數)。
然後h2然後h作爲主函數退出並且其局部變量被銷燬。

~HowMany2() 
    h copy: objectCount = 2   // destruction of x 
~HowMany2() 
    h copy copy: objectCount = 1  // destruction of h2 
~HowMany2() 
    h: objectCount = 0    // festruction of h 

如果你想變得真的很嚇人。在gcc上將優化轉換爲完全-O3或在VisStudio中以發佈模式構建。看看輸出如何不同。