std::unique_ptr析构函数顺序

std::unique_ptr destructor constructor order

本文关键字:析构函数 顺序 ptr unique std      更新时间:2023-10-16

我想知道当我将新unique_ptr分配给以前的unique_ptr时,会发生什么。在下面的代码中:

std::unique_ptr<my_class> test;
......
test = std::unique_ptr<my_class>(new my_class());
......
test = std::unique_ptr<my_class>(new my_class());

我希望当我第二次分配一个新的 std::unique_ptr 进行测试时,调用my_class的第一个析构函数,然后调用它的构造函数。我所期望的错了吗?但是当我调试我的代码时,我看到的是相反的。调用my_class的第一个构造函数,然后调用它的析构函数。

构造函数在前一个实例的析构函数之前调用的原因是因为您将new my_class()作为参数传递给unique_ptr的构造函数。首先计算参数,构造一个新的unique_ptr实例,该实例获得新创建对象的所有权,然后将该新unique_ptr实例分配给旧实例。

因此,旧unique_ptr拥有所有权的my_class对象将被释放和销毁,调用my_class析构函数。

它实际上与您编写的内容相同:

my_class* temp = new my_class;
test = std::unque_ptr<my_class>(std::move(temp));

在这里,可以直接看到首先构造新对象。

来自 cpp首选项:

unique_ptr& operator=( unique_ptr&& r ) noexcept;(1)
template< class> U, class E > unique_ptr& operator=( unique_ptr<U,E>&& r ) noexcept;(1)

将所有权从r转移到*this,就像通过调用一样reset(r.release())后跟get_deleter()分配std::forward<E>(r.get_deleter()).

如您所见,重置是在上一个指针上调用的,该指针执行以下操作:

  1. 保存当前指针的副本old_ptr = current_ptr
  2. 用参数current_ptr = ptr覆盖当前指针
  3. 如果旧指针为非空,则删除以前的托管对象if(old_ptr != nullptr) get_deleter()(old_ptr).