删除原始指针后访问weak_ptr

时间:2014-04-02 21:18:10

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

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

#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;
}

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

2 个答案:

答案 0 :(得分:2)

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&gt;锁定时会发生什么,你会得到一个包含NULL的shared_ptr。而((Test*)NULL)->valuep->value发生的事情,这是一个明显的段错误。

拥有weak_ptr的重点是允许用户安全地获取对可能超出范围的对象的引用。异常对此来说是一个糟糕的机制,因为异常是缓慢的,如果weak_ptr的父级超出范围,则不一定是致命的错误。因此,锁定机制或者在提升时返回新的计数引用,如果它不再提升所有权级别(父级已经过期),则返回NULL。

答案 1 :(得分:1)

您可以 read the documentation ,而不是假设事情是如何运作的。

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

所以,

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