问题描述
我使用了一个带有 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)
。