简体   繁体   English

转移唯一所有权:unique_ptr vs move语义

[英]Transferring sole ownership: unique_ptr vs move semantics

It seems like std::unique_ptr solves a problem that can also be solved with move-semantics, ie transferring ownership of a uniquely-owned resource. 似乎std::unique_ptr解决了一个问题,也可以通过移动语义来解决,即转移独有资源的所有权。 Here are some examples where they seem to perform the same job: 以下是他们似乎执行相同工作的一些示例:

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;
}

To my eye, these both solve almost exactly the same problem in slightly different ways. 在我看来,这两者都以稍微不同的方式解决了几乎完全相同的问题。 I'm not 100% clear on the advantages of one way versus the other. 我不是100%清楚单向与对方的优势。 I know that pointer moves are probably faster than move constructors/assignments, although both are usually assumed to be quite efficient. 我知道指针移动可能比移动构造函数/赋值更快,尽管通常认为两者都非常有效。 I'm also aware that move semantics allow you to keep your data on the stack (see r2, r4) instead of requiring a heap allocation/deallocation with new/malloc/etc (see r1, r3), which I think is a good thing (is it?). 我也知道移动语义允许你将数据保存在堆栈上(参见r2,r4)而不是要求使用new / malloc / etc(参见r1,r3)进行堆分配/释放,我认为这是一个好的事(是吗?)。

In general when should one prefer a unique_ptr over move semantics, or vice-versa? 通常什么时候应该更喜欢unique_ptr over move语义,反之亦然? Are there any use cases that can only be solved by one or the other? 是否有任何用例只能由一个或另一个解决?

If you have a class (perhaps written by someone else) which does not have a move constructor, perhaps not even a copy constructor, then you may have to use unique_ptr . 如果你有一个没有移动构造函数的类(可能由其他人编写),甚至可能不是复制构造函数,那么你可能必须使用unique_ptr

If an instance is optional, ie may not be present, you should use unique_ptr . 如果实例是可选的,即可能不存在,则应使用unique_ptr

If you can only initialize an object after your constructor is called, and the object is not default-constructible, you must delay construction, and can use unique_ptr for this. 如果只能在调用构造函数后初始化对象,并且该对象不是默认构造的,则必须延迟构造,并且可以使用unique_ptr

Even if a class has a move constructor, that might be more expensive than moving a single pointer. 即使一个类有一个移动构造函数,这可能比移动单个指针更昂贵。 For example, if the class contains dozens of POD instances, or an array. 例如,如果该类包含许多POD实例或数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM