返回物体时的ctor / dtor顺序

时间:2012-10-17 06:07:39

标签: c++ visual-studio-2010

此dtor / ctor订单是否正常,如果是,为什么?

在以下简单功能中

TemporaryObject SimpleFunction();
{
    TemporaryObject obj = MakeObj();

    // ...

    return obj;   // Stepping through at this point we hit TemporaryObject::dtor, MyObject::ctor
}

// At call site
MyObject obj = SimpleFunction();

在return语句中我希望调用MyObject ctor,然后调用TemporaryObject dtor。 (可能会先复制TemporaryObject,但这里只是RVO)。

VS2010(Debug build)中发生的事情是首先调用TemporaryObject dtor,然后使用被破坏的对象调用MyObject构造函数。查看内存地址确认它是被传递的被破坏对象,如果有任何疑问,析构函数的副作用是显而易见的。

(为了完整性,MyObject ctor在TemporaryObject中设置了一个标记它已经被复制的标志.TemporaryObject dtor声明这个标志被设置,这就是我知道在这种情况下'复制'之前发生破坏的方式)。

2 个答案:

答案 0 :(得分:1)

最小,完整的示例,有答案

是的,在复制构造函数之前调用dtor ,但不是出于您认为的原因。

关键观察是MyObject::dtor被调用两次(在两个不同的对象上,以防我们仍然倾向于跳到疯狂的编译器错误结论)。所以我们猜测副本是在幕后发生的,当然,尽管你可能已经听说过编译器 生成一个拷贝构造函数,即使你提供了不同的构造函数。

因此,如果您取消注释下面的复制构造函数,您将获得一些更好地描述正在发生的事情的输出,并且还正确处理mActive标志

struct TemporaryObject
{
    TemporaryObject()
        :
    mActive(true)
    { 
        std::cout << "TemporaryObject::ctor mActive = " << mActive << ", this = " << (void*)this << std::endl;
    }

   /* TemporaryObject(const TemporaryObject& obj)
        :
    mActive(obj.mActive)
    { 
        obj.mActive = false;
        std::cout << "TemporaryObject::copy_ctor mActive = " << mActive << ", this = " << (void*)this << std::endl;
    }*/

    ~TemporaryObject()
    {
        std::cout << "TemporaryObject::dtor mActive = " << mActive << ", this = " << (void*)this << std::endl;
        // assert(!mActive);
    }

    mutable bool mActive;
};

struct MyObject
{
    MyObject(const TemporaryObject& obj)
    {
        std::cout << "MyObject::ctor obj.mActive = " << obj.mActive << ", &obj = " << (void*)(&obj) << std::endl;
        obj.mActive = false;
    }
};

TemporaryObject SimpleFunction()
{
    TemporaryObject obj;

    // Do stuff

    return obj;
}

int main()
{
    MyObject obj = SimpleFunction();
}

输出:

TemporaryObject::ctor mActive = 1, this = 00EFF4AB
TemporaryObject::dtor mActive = 1, this = 00EFF4AB
MyObject::ctor obj.mActive = 1, &obj = 00EFF4D7
TemporaryObject::dtor mActive = 0, this = 00EFF4D7

答案 1 :(得分:0)

当然你在调试版本中看到了这一点。因为在调试版本中,从函数返回没有优化它具有以下规则:

TemporaryObject::ctor    // Copy constructor
TemporaryObject::dtor    // of function local value that reach end of its scope!
MyObject::ctor           // Create MyObject from returned value
TemporaryObject::dtor    // of function return value