当 unique_ptr 设置为 nullptr 时,谁以及何时删除对象

问题描述

我使用了一个带有 unique_ptr 指向对象的类,方法在运行时将它异步设置为 nullptr,然后另一个方法可能会调用 make_unique 并将提到的指针设置为这个新对象。

void Class0::f0()
{
    mPtr = std::make_unique<Class1>();
}

void Class0::f1(SomeType param)
{
    mPtr->doWork(param);
    mPtr      = nullptr; 
}

//f1 called after f0 asynchronIoUsly,any number of times

谁以及何时删除了未明确删除的前一个? unique_ptr 仍然存在,因为它是一个类字段,所以它的析构函数永远不会被调用,但是 unique_ptr 可以设置为 nullptr 并且 make_unique 可以被多次调用。 我几乎可以肯定它会导致内存泄漏,并且必须首先显式调用 mPtr.reset()。 但是我在visual studio c++中做了一个小测试,没有泄漏。

void f()
{
    std::unique_ptr<std::vector<std::vector<int>>> ptr = std::make_unique<std::vector<std::vector<int>>>(100000);
    ptr = nullptr;
    f();
}

递归只检查内存使用情况,有和没有 ptr = nullptr; 我已经尝试过使用 -O0 的 WSL g++,结果完全相同。有人可以解释一下吗?

解决方法

谁以及何时删除了未明确删除的前一个?

不显式删除智能指针管理的对象是首先使用智能指针的原因。要正确管理对象的生命周期,需要的不仅仅是删除 unique_ptr 的析构函数中的对象(请参阅 What is The Rule of Three?)。除非你做了一些奇怪的事情,否则假设智能指针正确管理生命周期是相当安全的。

这里的 ptr = nullptr; 是来自 cppreference/unique_ptr/operator= 的重载 (3):

unique_ptr& operator=( std::nullptr_t ) noexcept;     (3)     

实际上与调用 reset() 相同。

还有reset()

void reset( pointer ptr = pointer() ) noexcept;

替换托管对象。

给定由 *this 管理的指针 current_ptr,按顺序执行以下操作:

  • 保存当前指针的副本 old_ptr = current_ptr
  • 用参数 current_ptr = ptr 覆盖当前指针
  • 如果旧指针不为空,则删除之前管理的对象
    if(old_ptr) get_deleter()(old_ptr)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...