簡體   English   中英

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

[英]c++ weak_ptr expiring after dereference?

我是智能指針的新手,我試圖繞過我的腦袋,為什么在取消引用運算符之后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;
}

程序輸出weak ptr in d has expired.

我不明白為什么當d使用dereference運算符時,它會過期。 關於這一點,無論如何要防止它(除了不解除引用)?


我嘗試通過將節點中的weak_ptr更改為shared_ptr建議mrtnj ,但我認為我有內存泄漏。 我將node類更改為

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

然后修改源代碼以添加tryCreate函數。

void tryCreate()
{
    node d = *foo();
}

然后在我的main調用它,使我的主要看起來像

int main()
{
    tryCreate();
    return 0;
}

我使用Visual Studio 2015的內存分析,並注意到只有分配,沒有解除分配。 我將parent改為weak_ptr ,我看到了deallocations。 我做錯了什么,或者確實需要在這些循環條件下使用weak_ptr

當引用該對象的最后一個shared_ptr被銷毀時, weak_ptr到期。

在您的語句中發生的代碼中

node d = *foo();

這里foo()返回一個shared_ptr ,它是引用該對象的最后一個shared_ptr (由foo創建的兩個父對象)。 這個shared_ptr是一個臨時的,在derefencing之后就被摧毀了。 這會將引用計數減少到0並且weak_ptr過期。

由於shared_ptr是最后一個,因此該對象被銷毀,這導致其子對象也被銷毀。 因此,深入研究這些對象的后續代碼具有未定義的行為。

由於d包含對子節點的shared_ptr ,因此此時子節點不會被銷毀,如Miles Budnek在評論中所述。

node d = *foo();

foo返回一個shared_ptr ,它保持在foo分配的父節點處於活動狀態。

然后,將其內容復制到d但不存儲shared_ptr,以便在語句末尾銷毀。 現在沒有引用在foo中動態分配的節點實例的shared_ptr實例,因此對它的弱指針引用現在已過期。

取消引用不是問題:問題是無法捕獲返回的shared_ptr

這里:

node d = *foo();

你取消引用shared_ptr,所以d包含在foo中創建的node的副本:

shared_ptr<node> a = make_shared<node>();

這個a將在node d = *foo();之后被銷毀node d = *foo(); 這是因為parent只是一個weak_ptr內部節點。

關於這一點,無論如何要防止它(除了不解除引用)?

不解除引用似乎是好的方法。

你可以從 weak_tr<node> parent;切換 weak_tr<node> parent; shared_ptr<node> parent; 其他解決方案是保持全局shared_ptr<node> root; 哪個會引用你的a 但這取決於你的代碼到底要做什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM