【问题标题】:Accessing weak_ptr after deleting the original pointer删除原指针后访问weak_ptr
【发布时间】:2014-04-02 21:18:09
【问题描述】:

执行以下代码时出现运行时错误:

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

using namespace std;

class Test
{
public:
    int value;
    Test( )
    {
        value = 1;
    }

    ~Test( )
    {

    }
};

int main() {
    shared_ptr<Test> pTest =  shared_ptr<Test>( new Test( ) );
    std::vector<weak_ptr<Test>> testList;

    testList.push_back( weak_ptr<Test>(pTest) );
    cout << "\n Before Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
        try
        {
            auto p = testList[i].lock();
            cout << "\n Item not null: " << p->value;
        }
        catch (bad_weak_ptr b)
        {
            wcout << L"Null object" << endl;
        }
    }

    pTest.reset( );

    cout << "\n After Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
        try
        {
            auto p = testList[i].lock();
            cout << "\n Item not null: " << p->value;
        }
        catch (bad_weak_ptr b)
        {
            wcout << L"Null object" << endl;
        }
    }

    // your code goes here
    return 0;
}

我试图在删除原始共享指针后查找指针是否仍然可以访问(不应该)。

【问题讨论】:

标签: c++ vector shared-ptr weak-ptr


【解决方案1】:

Lock 不检查 null,它会将 weak_ptr 提升为共享指针。删除对象时不会抛出异常,而是返回null。

这是你应该做的。

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

using namespace std;

class Test
{
public:
    int value;
    Test( )
    {
        value = 1;
    }

    ~Test( )
    {

    }
};

int main() {
    shared_ptr<Test> pTest =  shared_ptr<Test>( new Test( ) );
    std::vector<weak_ptr<Test>> testList;

    testList.push_back( weak_ptr<Test>(pTest) );
    cout << "\n Before Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
      auto p = testList[i].lock();
        if (p)
        {

            cout << "\n Item not null: " << p->value;
        }
        else
        {
            wcout << L"Null object" << endl;
        }
    }

    pTest.reset( );

    cout << "\n After Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
      auto p = testList[i].lock();
        if (p)
        {

            cout << "\n Item not null: " << p->value;
        }
        else
        {
            wcout << L"Null object" << endl;
        }
    }

    // your code goes here
    return 0;
}

澄清一下,当您在 pTest 重置后对 test_list>lock 时会发生什么,您会得到一个包含 NULL 的 shared_ptr。而((Test*)NULL)-&gt;value 是当您执行p-&gt;value 时会发生的情况,这是一个明显的段错误。

拥有weak_ptr 的全部意义在于让用户能够安全地获取对可能超出范围的对象的引用。异常将是一个糟糕的机制,因为异常是缓慢的,如果weak_ptr的父级超出范围,它不一定是致命错误。所以机制是 lock 要么在提升时返回一个新的计数引用,要么如果它不能再提升所有权级别(父级已过期)则返回 NULL。

【讨论】:

    【解决方案2】:

    您可以read the documentation,而不是对事情的运作方式做出假设。

    lock 不会通过抛出异常来表示空指针:它返回一个空指针。

    所以,

            auto p = testList[i].lock();
            if( p != nullptr )
            {
                cout << "\n Item not null: " << p->value;
            }
            else
            {
                cout << "\n Item is null." << endl;
            }
    

    【讨论】:

    • 感谢您的回复。我的示例来自本教程:msdn.microsoft.com/en-us/library/hh279672.aspx
    • @ssk:该 Microsoft 操作指南页面(lock 抛出)中提供的信息不正确,并且代码具有很强的误导性。此类操作方法文章或教程不是文档。好的教程(这是一个非常糟糕的教程)可以指导您,但除此之外您还需要查阅技术文档。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 2017-05-06
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 2015-01-02
    • 2021-07-30
    相关资源
    最近更新 更多