2010-12-19 42 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中以发布模式构建。看看输出如何不同。