Используете ли shared_ptr после сброса неопределенное поведение? - PullRequest
1 голос
/ 16 октября 2019

У меня есть эта тестовая программа:

#include <iostream>
#include <memory>

class A {
public:
    A()
    {
        std::cout<<"A Constructor\n";
    }

    ~A(){
        std::cout<<"A Destructor\n";
    }

    void show()
    {
        std::cout<<"A::show()"<<'\n';
    }
};

int main()
{
    auto p1 = std::make_shared<A>();
    // Relinquishes ownership of p1 on the object
    // and pointer becomes NULL
    p1.reset();
    std::cout<<p1.get()<<'\n';
    std::cout<<p1.use_count()<<'\n';
    p1->show();
    return 0;
}

Который дает этот вывод:

A Constructor
A Destructor
0
0
A::show()

Я запустил это через GDB и увидел:

:
:
(gdb) s
A::show (this=0x0) at so.cpp:18
18              std::cout<<"A::show()"<<'\n';
(gdb) s
A::show()
:

строка A::show (this=0x0) at so.cpp:18 указывает, что базовый ресурс равен нулю. Я посмотрел на другой вопрос, но там для вызова функции-члена использовался необработанный указатель. Является ли этот случай слишком похожим на тот, что в этом вопросе, поскольку p1->show() тоже должен быть эквивалентен чему-то вроде p1.get()->show();. Правильно ли мое понимание?

1 Ответ

0 голосов
/ 16 октября 2019

Просто добавьте элемент данных в класс, и вы увидите визуально неопределенное поведение.

#include <iostream>
#include <memory>

class A {
public:
    A()
    {
        std::cout<<"A Constructor\n";
    }

    ~A(){
        std::cout<<"A Destructor\n";
    }

    void show()
    {
        std::cout<<"A::show()"<<'\n';
        ++x;
    }

    int x = 0;
};

int main()
{
    std::shared_ptr<A> p1(new A);
    // Relinquishes ownership of p1 on the object
    // and pointer becomes NULL
    p1.reset();
    std::cout<<p1.get()<<'\n';
    std::cout<<p1.use_count()<<'\n';
    p1->show();
    return 0;
}

Например, во время выполнения может отображаться такая ошибка

Runtime error #stdin #stdout 0s 4280KB

.

То есть нулевой указатель использовался для доступа к элементу данных.

...