就释放而言,unique_ptr <t> :: operator =做什么

时间:2018-09-11 12:39:38

标签: c++11

我无法完全理解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(新A())的内容会被自动破坏? 还是我应该选择:

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

3 个答案:

答案 0 :(得分:4)

是的,请参见C++11 draft standard的第20.9.1节第4段

  

另外,您可以根据请求将所有权转移到另一个唯一指针u2。完成后   进行这样的转移时,必须满足以下条件:

     
      
  • u2.p等于转移前的u.p,
  •   
  • u.p等于nullptr,并且
  •   
  • 如果转移前u.d保持状态,则该状态已转移到u2.d。
  •   
     

与重置一样, u2必须通过预转移正确处置其预转移拥有的对象   所有权转移完成之前,关联的删除程序

换句话说,它会按照您的期望自动清除。

答案 1 :(得分:1)

是的,替换智能指针的内容将释放以前保留的资源。您无需显式调用reset()(也不会有人期望您)。

答案 2 :(得分:1)

仅出于此特定示例。您的示例中的多态似乎不允许您从输出中得出明确的结论:

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

Online

我希望这不会造成误解。