Что делает unique_ptr <T>:: operator = с точки зрения освобождения - PullRequest
0 голосов
/ 11 сентября 2018

У меня проблемы с полным пониманием оператора присваивания для unique_ptr. Я понимаю, что мы можем перемещать их только из-за того, что конструктор копирования и операторы присваивания удалены, но что если unique_ptr, который уже содержит выделение, перезаписывается операцией перемещения? Содержимое, ранее сохраненное в смарт-указателе, свободно?

#include <iostream>
#include <memory>

class A{
public:
    A() = default;
    virtual void act() const {
        std::cout << "act from A" << std::endl;
    }
    virtual ~A() {
        std::cout << "destroyed A" << std::endl;
    }
};
class B : public A {
public:
    B() : A{} {}
    void act() const override {
        std::cout << "act from B" << std::endl;
    }

    ~B() override {
        std::cout << "destroyed from B " << std::endl;
    }
};
int main() {
    auto pP{std::make_unique<A>()};
    pP->act();

    ==================== ! =======================
    pP = std::make_unique<B>(); // || std::move(std::make_unique<B>())
    ==================== ! =======================

    pP->act();
    return 0;
}

Когда я делаю

pP = std::make_unique<B>();

означает ли это, что то, что было выделено в первых строках для pP (new A ()), уничтожается автоматически? Или я должен выбрать:

pP.reset();
pP = std::make_unique<B>();

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

Да, см. Раздел 20.9.1, пункт 4 проекта стандарта C ++ 11

Кроме того, по запросу вы можете передать право собственности на другой уникальный указательu2.После завершения такого перевода выполняются следующие постусловия:

  • u2.p равно предварительному переводу up,
  • up равно nullptr и
  • если предварительная передача ud поддерживала состояние, то такое состояние было передано в u2.d.

Как и в случае сброса, u2 должен правильно утилизировать свою предварительную передачупринадлежащий объект с помощью связанного с ним средства удаления перед передачей до того, как передача права собственности считается завершенной

Другими словами, он очищает себя после присвоения, как и следовало ожидать.

0 голосов
/ 11 сентября 2018

Просто ради этого конкретного примера. Кажется, полиморфизм в вашем примере не позволил вам сделать четкие выводы из вывода:

act from A
destroyed A
act from B
destroyed from B 
destroyed A

Итак, давайте упростим ваш пример и приведем его к сути:

#include <iostream>
#include <memory>

struct A {
    explicit A(int id): id_(id)
    {}

    ~A()
    {
        std::cout << "destroyed " << id_ << std::endl;
    }

    int id_;
};

int main() {
    std::unique_ptr<A> pP{std::make_unique<A>(1)};
    pP = std::make_unique<A>(2);
}

который выводит:

destroyed 1
destroyed 2

Интернет

Надеюсь, это не оставляет места для неправильного толкования.

0 голосов
/ 11 сентября 2018

Да, замена содержимого интеллектуального указателя приведет к освобождению ранее удерживаемого ресурса. Вам не нужно звонить reset() явно (и никто не будет ожидать от вас).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...