c ++ weak_ptr在取消引用后到期了吗?

sil*_*twf 4 c++ smart-pointers weak-ptr

我是智能指针的新手,我试图绕过我的脑袋,为什么在取消引用运算符之后weak_ptr会过期.我以前测试的代码在这里:

#include <memory>
#include <iostream>
#include <vector>

using namespace std;

struct node
{
    weak_ptr<node> parent;
    shared_ptr<node> child;
    int val;
};

shared_ptr<node> foo()
{
    shared_ptr<node> a = make_shared<node>();
    shared_ptr<node> b = make_shared<node>();

    a->val = 30;
    b->val = 20;

    b->parent = a;
    a->child = b;

    return a;
}

int main()
{
    shared_ptr<node> c = foo();
    node d = *foo();

    if (c->child->parent.expired())
    {
        cout << "weak ptr in c has expired." << endl;
    }

    if (d.child->parent.expired())
    {
        cout << "weak ptr in d has expired." << endl;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该计划的产出 weak ptr in d has expired.

我不明白为什么当d使用dereference运算符时,它会过期.关于这一点,无论如何要防止它(除了不解除引用)?


我尝试通过更改in节点建议mrtnjweak_ptr,shared_ptr但我认为我有内存泄漏.我将node班级改为

struct node
{
    shared_ptr<node> parent;
    shared_ptr<node> child;
    int val;
};
Run Code Online (Sandbox Code Playgroud)

然后修改源代码以添加tryCreate功能.

void tryCreate()
{
    node d = *foo();
}
Run Code Online (Sandbox Code Playgroud)

然后在我main这样称呼它,使我的主要看起来像

int main()
{
    tryCreate();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我使用Visual Studio 2015的内存分析,并注意到只有分配,没有解除分配.我变成parent了一个weak_ptr,我看到了deallocations.我做错了什么,或者确实要求weak_ptr在这些循环条件下使用?

Che*_*Alf 6

一个weak_ptr当最后到期shared_ptr是指对象,被销毁.

在您的语句中发生的代码中

node d = *foo();
Run Code Online (Sandbox Code Playgroud)

这里foo()返回一个shared_ptr,它是shared_ptr引用该对象的最后一个(由两个创建的父对象foo).shared_ptr在derefencing之后,这是一个在那里被摧毁的临时性.这会将引用计数减少到0并且weak_ptr到期.

由于它shared_ptr是最后一个,因此对象被销毁,这导致其子对象也被销毁.因此,深入研究这些对象的后续代码具有未定义的行为.

由于d包含a shared_ptr到子节点,因此此时子节点不会被销毁,正如Miles Budnek在评论中所指出的那样.