转移唯一所有权:unique_ptr与移动语义
Transferring sole ownership: unique_ptr vs move semantics
似乎std::unique_ptr
解决了一个也可以通过移动语义解决的问题,即转移唯一拥有的资源的所有权。以下是一些他们似乎执行相同任务的例子:
class SomeResource { /* resourcey stuff */ };
void ProcessResourcePtr(std::unique_ptr<SomeResource> r) { /* do stuff */ }
void ProcessResourceRvalRef(SomeResource&& r) { /* do stuff */ }
class OwnerOfResourcePtr {
private:
std::unique_ptr<SomeResource> r_;
public:
OwnerOfResourcePtr(std::unique_ptr<SomeResource> r) : r_(std::move(r)) { }
};
class OwnerOfResourceRvalRef {
private:
SomeResource r_;
public:
OwnerOfResourceRvalRef(SomeResource&& r) : r_(std::move(r)) { }
};
int main()
{
// transfer ownership to function via unique_ptr
std::unique_ptr<SomeResource> r1(new SomeResource());
ProcessResourcePtr(std::move(r1));
// transfer ownership to function via rvalue ref
SomeResource r2;
ProcessResourceRvalRef(std::move(r2));
// transfer ownership to instance via unique_ptr
std::unique_ptr<SomeResource> r3(new SomeResource());
OwnerOfResourcePtr(std::move(r3));
// transfer ownership to instance via rvalue ref
SomeResource r4;
OwnerOfResourceRvalRef(std::move(r4));
return 0;
}
在我看来,这两者以略微不同的方式解决了几乎完全相同的问题。我不是100%清楚一种方式与另一种方式的优势。我知道指针移动可能比移动构造函数/赋值更快,尽管通常认为两者都非常有效。我还知道,移动语义允许您将数据保留在堆栈上(请参阅r2,r4),而不需要使用new/malloc/etc进行堆分配/释放(请参阅r1,r3),我认为这是一件好事(是吗?)。
一般来说,什么时候应该更喜欢unique_ptr
而不是移动语义,或者反之亦然?是否有任何用例只能由其中一个或另一个解决?
如果您有一个类(可能是由其他人编写的)没有移动构造函数,甚至可能没有复制构造函数,那么您可能必须使用unique_ptr
。
如果实例是可选的,即可能不存在,则应使用unique_ptr
。
如果只能在调用构造函数后初始化对象,并且该对象不是默认可构造对象,则必须延迟构造,并且可以为此使用unique_ptr
。
即使一个类有一个移动构造函数,也可能比移动单个指针更昂贵。例如,如果类包含数十个POD实例或一个数组。
相关文章:
- 将对象移动到std::shared_ptr
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 将shared_ptr移动到<StructA>shared_ptr<变体<结构A、结构 B>>
- C / C++ 移位/偏移/向左或向右移动位图?
- MSVC将仅移动结构参数解释为指针
- 自定义先决条件对移动分配运算符有效吗
- 返回值优化:显式移动还是隐式
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- CLANG 编译器 说:变量"PTR"可能未初始化
- 可以使用移动语义更改或改进此C++代码吗?
- 使lambda不可复制/不可移动
- c++在使用指针时移动语义
- 将QGraphicsItem的移动区域限制在多边形区域内
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- SendInput()鼠标移动计算
- 按值 C++ 返回时进行双倍移动
- 唯一 ptr 将所有权移动到包含对象的方法
- 独特的PTR和移动语义