Доступ к 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 ответа

Решение

Блокировка не проверяет нулевое значение, она переводит слабый_портр в общий указатель. Это не бросает, когда объект удален, но скорее возвращает нуль.

Это то, что вы должны делать.

#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, вы получаете shared_ptr, который содержит NULL. а также ((Test*)NULL)->value это то, что происходит, когда вы делаете p->value, который является очевидным сегментом.

Весь смысл слабого_птр состоит в том, чтобы дать пользователям возможность безопасно получить ссылку на объект, который может выйти за рамки видимости. Исключения могли бы быть плохим механизмом для этого, потому что исключения являются МЕДЛЕННЫМИ, и это не обязательно фатальная ошибка, если родительский объект weak_ptr выходит из области видимости. Таким образом, механизм блокировки либо возвращает новую подсчитанную ссылку при повышении, либо NULL, если он больше не может повышать уровень владения (срок действия родительского элемента истек).

Вы можете читать документацию, а не делать предположения о том, как все работает.

lock не сигнализирует нулевой указатель, выдавая исключение: он возвращает нулевой указатель.

Так,

        auto p = testList[i].lock();
        if( p != nullptr )
        {
            cout << "\n Item not null: " << p->value;
        }
        else
        {
            cout << "\n Item is null." << endl;
        }
Другие вопросы по тегам