unique_ptr владение сумасшествием - PullRequest
1 голос
/ 01 февраля 2020

Посмотрите на приведенный ниже пример кода и его вывод.

У меня есть простой Base класс с просто int * переменной-членом.

Я создаю unique_ptr из существующего объекта Base.

Когда указатель и объект выходят из области видимости, деструктор вызывается дважды, сначала для unique_ptr, а затем для объекта.

Я думал, что unique_ptr будет владельцем объекта и позаботится о его уничтожении ??

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

class Base
{
protected:
    int* status;

public:
    // default constuctor
    Base() : Base(0)
    {
    }

    // custom constuctor
    Base(int a){
        this->status = new int(a);
        std::cout << "\n" << "Base:" << *status;
    }

    // destructor
    ~Base(){
        std::cout << "\n" << "Base Destroyed:" << *status;
        delete this->status;
    }

    void info(){
        std::cout << "\n" << "Base status:" << *status;
    }    
};

int main(int argc, const char * argv[])
{
    {
        Base base(1);

        // create from existing object
        std::unique_ptr<Base> uptrBase1 = std::make_unique<Base>(base);

        // create from new
        std::unique_ptr<Base> uptrBase3 = std::make_unique<Base>();

        std::cout<<"\n" << "Ending scope";
    }

    std::cout<<"\n";
    return 0;
}

Вывод, который я получаю, такой:

Base:1
Base:0
Ending scope
Base Destroyed:0
Base Destroyed:1
Base Destroyed:0TestCppProject(4373,0x1000d5dc0) malloc: *** error for object 0x1005ac970: pointer being freed was not allocated
TestCppProject(4373,0x1000d5dc0) malloc: *** set a breakpoint in malloc_error_break to debug
Program ended with exit code: 9

1 Ответ

3 голосов
/ 01 февраля 2020

Я думал, что unique_ptr будет владеть объектом и позаботится о его уничтожении ??

Вы не можете стать владельцем автоматического c объекта продолжительности хранения. Время жизни таких объектов контролируется компилятором и заканчивается в конце блока, в котором они определены. Период. Что делает эта строка:

std::unique_ptr<Base> uptrBase1 = std::make_unique<Base>(base);

создает динамический c объект продолжительности хранения и инициализирует его с base. Ie логически этот код равен:

Base *ptr = new Base( base );
std::unique_ptr<Base> uptrBase1( ptr );

, поэтому вы делаете копию base и передаете владение этим вновь созданным объектом uptrBase1. Когда вы нарушили Что такое Правило Трех? это приводит к UB из-за двойного разрушения внутреннего указателя, созданного вами внутри класса Base, и когда вы создали 3 объекта типа Base, его деструктор вызывается 3 раза .

Кстати: если вы следуете практике и компилятор status std::unique_ptr не позволит вам нарушить правило, а упомянутая выше строка не скомпилируется.

...