C++ 如何使用移动语义正确管理资源? structfoo{ int*i; foo():i(新int(42)){} foo(const foo&)=删除; foo(foo&&)=默认值; ~foo(){ std::cout
您需要定义move构造函数以防止从moved from对象中删除:C++ 如何使用移动语义正确管理资源? structfoo{ int*i; foo():i(新int(42)){} foo(const foo&)=删除; foo(foo&&)=默认值; ~foo(){ std::cout,c++,move,c++14,move-semantics,C++,Move,C++14,Move Semantics,您需要定义move构造函数以防止从moved from对象中删除: struct foo{ int* i; foo(): i(new int(42)){} foo(const foo&) = delete; foo(foo&&) = default; ~foo(){ std::cout << "destructor: i" << std::endl; delete(i); } }; int main() {
struct foo{
int* i;
foo(): i(new int(42)){}
foo(const foo&) = delete;
foo(foo&&) = default;
~foo(){
std::cout << "destructor: i" << std::endl;
delete(i);
}
};
int main()
{
foo f;
auto sp_f = std::make_shared<foo>(std::move(f));
}
现在,当运行旧对象的析构函数时,它不会删除i
,因为删除空指针是不可操作的
您还应该定义一个移动赋值运算符,并删除复制赋值运算符。这实际上是五条规则。如果您有一个可以从中移动的类,您应该自己定义移动语义(加上复制、析构函数等)
至于如何做到这一点,请引用“……从中移动的对象被置于有效但未指定的状态。”未指定的状态通常是对象在默认初始化时的样子,或者如果对象被调用了swap
,会发生什么情况
正如@zenith所回答的,一种简单的方法是让移动构造函数(或赋值操作符)将原始指针设置为nullptr
。这样,数据不会被释放,原始对象仍然处于有效状态
另一个常见的习惯用法是,如前所述,使用swap
。如果类需要自己的复制和移动语义,那么swap
方法也很方便。移动构造函数将初始化委托给默认构造函数,然后调用swap
方法。在移动赋值操作符中,只需调用swap
>。要移入的对象将获得资源,而另一个对象的析构函数将释放原始资源
通常是这样的:
foo(foo&& f): i(f.i) {
f.i = nullptr;
}
不要默认移动构造函数?是的,实际上定义了移动cter和交换指针,例如,或者使用已经定义了移动语义的东西,比如“代码> STD::UnQuyGPPT/<代码>,而不是原始数组,只使用<代码> STD::vector < /Calp>。所有的OK。管理C++中资源的关键是使用标准RESU。rce管理器。至少要尽可能多。@chearsandhth.-Alf我在这里没有看到原始数组。在这种情况下,您可以使用
unique\u ptr I
和零规则。如果资源需要其他发布代码,您还可以使用自定义删除器使用unique\u ptr
。避免重新发明轮子很好!如果我的用例不需要呢这么简单?如果我需要调用delete\u某物(某个句柄)
而没有“noop”怎么办对于某些默认值并调用它两次会有问题吗?您可以始终使用布尔标志来标记是否清理资源。@MaikKlein我不太明白。您能否提供一个更详细的示例,可能在原始问题中?class foo
可以有一个成员bool shouldDestroy代码>将在销毁时进行检查。如果为true
,则销毁资源。您可以编写std::swap(resource,rhs.resource);
struct Foo
{
void* resource; //managed resource
Foo() : resource(nullptr) {} //default construct with NULL resource
Foo(Foo&& rhs) : Foo() //set to default value initially
{
this->swap(rhs); //now this has ownership, rhs has NULL
}
~Foo()
{
delete resource;
}
Foo& operator= (Foo&& rhs)
{
this->swap(rhs); //this has ownership, rhs has previous resource
}
void swap(Foo& rhs) //basic swap operation
{
std::swap(resource, rhs.resource); //thanks @M.M
}
};