为什么匿名 unique_ptr 值会立即被破坏

Why does anonymous unique_ptr value get destructed instantly

如果对象 unique_ptr<A> 匿名传递(或根本不传递给任何变量),它的行为如何。怎么可能知道 unique_ptr 是否有来自 c'tor 的引用(它被设置到命名变量中)。

基本上,该示例显示了直接从返回值对象调用方法 get() 方法。

class A
{
public:
    A(int a):_a(a) {}
    ~A() { std::cout << "d'tor A " << _a << std::endl; }
    int _a;
};


std::unique_ptr<A> f1()
{
    auto p1 = std::make_unique<A>(1);
    return p1;
}

A *f2()
{
    A * x = std::make_unique<A>(2).get(); // d'tor called 2
    std::cout << x->_a << std::endl; // this will print 2 although destructed.
    return x;
}

A *f3()
{
    return std::make_unique<A>(3).get(); // d'tor called 3
}


int main(int argc, const char * argv[]) {
    auto a=f1();
    auto b=f2();
    auto c=f3();

    return 0;
} // d'tor called 1

在上面的代码中,我理解了 d'tor A 1 调用的时间,因为在退出唯一引荐来源网址(由局部变量 a 表示)被销毁的块时。

但我不明白其他 2 个流程(d'tor A 2d'tor A 3 在创建过程中调用 - 请参见示例)。这是否意味着在这些情况下引用计数从一开始就为 0,或者它增加到 1 并在之后立即减少。

P.S

这个案例让我很感兴趣,虽然它与任何真实案例无关,但澄清了我偶然处理的一个概念。

发生这种情况是因为我转换了 java-脚本,它被设置为创建一个成员并在没有中间变量的情况下使用它(例如 a().b().c() 而不是 _a=a(); _b=_a.b(); _c=_b.c())并且我不小心使用了我的 C++ 代码中的这个符号。

您混淆了 std::unique_ptr 和它管理的对象的生命周期,以及您可以使用它的 get 方法获得的指针的生命周期。

A std::unique_ptr 是动态分配对象的唯一所有者,当它的析构函数被调用时,它会在它持有的指针上调用删除辅助函数(在 std::make_unique 的情况下,它只会调用 deletedelete[],以在这种情况下合适的为准)

在第一种情况下,变量 a 的类型是 std::unique_ptr<A>std::unique_ptr 存在于堆栈中,(您不必调用 std::move感谢复制省略),当 main 函数完成时,它从堆栈中删除,调用析构函数,并删除对象,这是我们在使用 std::unique_ptr 时通常想要的行为。

现在,第二种情况和第三种情况一样,第二种情况只是引入了一个临时变量,但它没有改变任何东西。

A * x = std::make_unique<A>(2).get();

当这样调用时,您会创建一个临时 std::unique_ptr<A>,并在该临时上调用 get 方法,即 returns 受管理指针的副本。问题是临时的 std::unique_ptr<A> 在行尾被销毁,而你的指针是悬空的,它已经被删除了。取消引用并以任何方式使用是未定义的行为,任何事情都可能发生。

第 3 种情况相同,临时 std::unique_ptr,您得到它的指针,但临时已被删除,因此在它管理的对象上调用 delete,我们有一个悬空指针。

每当你有一个智能指针时,永远不要在临时变量上调用 get,首先将临时变量存储在局部变量中,这样当你仍在使用它时它不会超出范围正在管理。