0

我正在学习 C++。我刚刚了解到std::shared_ptr可以像引用计数方式一样管理堆分配的对象。

目前我的编译器(Xcode/Clang/C++11)显示了我想要的确切行为。打印这个结果,

Step0
Step1
CREATED!
Step2
Step3
Step5
DESTROYED!
Step6

使用此代码。

class   Obj1
{
    public:
        Obj1() { printf("CREATED!\n"); }
        ~Obj1() { printf("DESTROYED!\n"); }
};

std::shared_ptr<Obj1> func1 ()
{
    printf("Step0\n");
    {
        printf("Step1\n");
        std::shared_ptr<Obj1>   o1(new Obj1());
        printf("Step2\n");
        std::shared_ptr<Obj1>   o2  =   o1;
        printf("Step3\n");
        return  o2;
    }
    printf("Step4\n");
}



int main(int argc, const char * argv[])
{
    {
        std::shared_ptr<Obj1>   o3  =   func1();
        printf("Step5\n");
    }
    printf("Step6\n");
    return 0;
}

但据我所知,当std::shared_ptr分配给新变量时,C++ 的复制构造函数优化可能会发生这种情况。(我不确定名称...)如果是,Obj1则在从函数返回时实例可能不能保证是活动的,因为实际上shared_ptr它在调用者语义上被销毁并重新创建。

当然,所有这些都是新手的假设。请让我知道在这种情况下对对象生命周期的实际预期。

PS。这源于我之前的问题: 清理堆分配对象的良好做法或约定?

4

2 回答 2

4

要么o2的生命周期被延长,要么在它被销毁之前制作它的副本。无论哪种方式,至少有一个shared_ptr始终存在,因此代码是安全的。

于 2013-02-28T04:00:02.527 回答
4

您误解了该优化的工作原理。假设我们有一个小例子:

std::shared_ptr<Foo> func()
{
    std::shared_ptr o2;
    o2.reset( new Foo  );
    return o2;
}
std::shared_ptr<Foo> o1 = func();

编译器可以通过优化做什么看起来像这样(不完全是,但有助于理解这个想法):

void func( std::shared_ptr<Foo> &o2 )
{
    o2.reset( new Foo  );
}
std::shared_ptr<Foo> o1;
func( o1 );

因此,从您的角度来看,几乎没有任何变化,只消除了对象的副本(智能指针)。它不会影响 Foo 的生命周期。

于 2013-02-28T04:17:52.293 回答