Ant*_*Ant 2 c++ smart-pointers move-semantics
我有以下代码:
\nstd::unique_ptr<T> first = Get();\n\xe2\x80\xa6\nT* ptr_to_class_member = GetPtr(obj);\n*ptr_to_class_member = std::move(*first.release());\nRun Code Online (Sandbox Code Playgroud)\n这是否会按预期运行,没有副本、1 次移动并且没有内存泄漏?
\n*ptr_to_class_member = std::move(*first.release());
Run Code Online (Sandbox Code Playgroud)
只需调用 的 移动赋值运算符,T并将其指向的对象first作为参数。这可能会正确传输一些数据,但delete不会被调用或对象,因此既不会T::~T执行,也不会释放对象的内存。
在这个示例中T = std::string,将导致字符串对象的后备存储正确地从移动分配的右侧转移到左侧,但动态分配的内存大小sizeof(std::string)仍然会泄漏。
对于某些类,缺少对象的析构函数调用可能会导致额外的麻烦,因为移动分配只需要使 rhs 处于未指定但有效的状态,这可能仍然需要释放额外的资源。
你需要做
*ptr_to_class_member = std::move(*first);
first.reset();
Run Code Online (Sandbox Code Playgroud)
以防止内存泄漏。
为了显示这里出了什么问题,以下代码实现了内存(取消)分配和特殊成员函数的打印:
#include <iostream>
#include <memory>
#include <new>
#include <utility>
struct TestObject
{
TestObject()
{
std::cout << "TestObject::TestObject() : " << this << '\n';
}
TestObject(TestObject&& other)
{
std::cout << "TestObject::TestObject(TestObject&&) : " << this << ", " << &other << '\n';
}
TestObject& operator=(TestObject&& other)
{
std::cout << "TestObject::operator=(TestObject&&) : " << this << ", " << &other << '\n';
return *this;
}
~TestObject()
{
std::cout << "TestObject::~TestObject() : " << this << '\n';
}
void* operator new(size_t size)
{
void* const result = ::operator new(size);
std::cout << "memory allocated for TestObject: " << result << '\n';
return result;
}
void operator delete(void* mem)
{
std::cout << "memory of TestObject deallocated: " << mem << '\n';
::operator delete(mem);
}
};
template<class Free>
void Test(Free free, char const* testName)
{
std::cout << testName << " begin -------------------------------------------\n";
{
auto ptr = std::make_unique<TestObject>();
std::cout << "object creation done\n";
free(ptr);
}
std::cout << testName << " end ---------------------------------------------\n";
}
int main()
{
TestObject lhs;
Test([&lhs](std::unique_ptr<TestObject>& ptr)
{
lhs = std::move(*ptr);
ptr.reset();
}, "good");
Test([&lhs](std::unique_ptr<TestObject>& ptr)
{
lhs = std::move(*ptr.release());
}, "bad");
}
Run Code Online (Sandbox Code Playgroud)
可能的输出:
TestObject::TestObject() : 0000009857AFF994
good begin -------------------------------------------
memory allocated for TestObject: 000001C1D5715EF0
TestObject::TestObject() : 000001C1D5715EF0
object creation done
TestObject::operator=(TestObject&&) : 0000009857AFF994, 000001C1D5715EF0
TestObject::~TestObject() : 000001C1D5715EF0
memory of TestObject deallocated: 000001C1D5715EF0
good end ---------------------------------------------
bad begin -------------------------------------------
memory allocated for TestObject: 000001C1D5715EF0
TestObject::TestObject() : 000001C1D5715EF0
object creation done
TestObject::operator=(TestObject&&) : 0000009857AFF994, 000001C1D5715EF0
bad end ---------------------------------------------
TestObject::~TestObject() : 0000009857AFF994
Run Code Online (Sandbox Code Playgroud)
您可以清楚地看到第二种情况下缺少析构函数调用和释放,这与您所询问的代码相匹配。