2014-10-11 374 views
20

C++11我们可以使用std::move()将对象的所有权转让给另一个unique_ptr。股权转让完成后,即割让所有权的智能指针变为nullget()返回nullptr.将对象的所有权从一个unique_ptr转移到C++ 11中的另一个unique_ptr?

std::unique_ptr<int> p1(new int(42)); 
std::unique_ptr<int> p2 = std::move(p1); // Transfer ownership 

什么在哪里,因为它是转移所有权转让给其他unique_ptr这将是非常有用的情况呢?

+4

就是这样。标准库中的智能指针不应该被看作是自动释放的指针,而是根据*所有权*。你有一些数据只能由一个实体“拥有”,然后使用唯一的指针。 – 2014-10-11 19:41:07

+4

当您使用线程或套接字等不可复制的数据进行工作时,并且您需要将其从一个位置替换为另一个位置(例如,将其放入向量中),这非常有用。 – wowofbob 2014-10-11 19:59:55

回答

2

例如,如果你调用一个函数,你可以在参数列表moveunique_ptr因此它可以是你的函数签名

foo (std::unique_ptr<T>&& ptr) 

的一部分,你可以调用foo与

foo(std::move(myPtr)); 

std::move是无条件转换,unique_ptr是具有状态的对象,并且该状态的一部分是unique_ptr管理的指针,其中std::move荷兰国际集团整个对象,你是不是真的改变了人们拥有什么,没有什么特别之处std::unique_ptr同时使用std::move因为std::move并不真正关心什么具体的,我说这是一个无条件的演员和unique_ptr简单地被浇铸成型,整个作为unique_ptr<T>类型实例的对象被铸造。

如果您想谈谈您的unique_ptr指出的对象的所有权转让,您应该考虑std::unique_ptr<T>本身提供的swap

+1

当您将'move'移动到另一个'unique_ptr'时,'unique_ptr'传输管理对象的所有权。 – 2014-10-12 00:43:22

+0

@JonathanPotter在语义上是不正确的,'move'什么也不做,只是一个强制转换,其语义是关于将表达式变为右值,而不是在'unique_ptr'的情况下转移所有权,当函数调用将会发生,那'unique_ptr'将被移动,这是一个副作用,如果你的目的是改变所有权这是用错误的语义做这件事最神秘的方式,只是不这样做,使用'swap',它具有正确的语义,它只是做你想做的。 – user2485710 2014-10-12 06:58:36

+0

说实话,我不太清楚你的意思。但是,如果使用'move'将'unique_ptr' push_back到'vector'中,你会怎么想呢? – 2014-10-12 07:35:41

19

以下情形涉及从一个unique_ptr转移到另一个所有权:从函数返回,并作为参数传递给像一个构造函数。

说你有一些多态型Animal

struct Animal { 
    virtual ~Animal() {} 
    virtual void speak() = 0; 
}; 

与具体子类CatDog

struct Cat : Animal { 
    void speak() override { std::cout << "Meow!\n"; } 
}; 

struct Dog : Animal { 
    void speak() override { std::cout << "Woof!\n"; } 
}; 

你想要一个简单的工厂,创建基于服从的要求值的宠物。然后工厂必须返回一个指针。我们希望宠物工厂创建宠物的所有权转移给调用者这样一个合理的返回类型为std::unique_ptr<Animal>

std::unique_ptr<Animal> createPet(double obedience) { 
    if (obedience > 5.0) 
    return std::make_unique<Dog>(); 
    return std::make_unique<Cat>(); 
} 

现在,假设我们要创建一个House将拥有的宠物那么我们可能会想传递宠物进入House的构造函数。还有一些争议(see comments on this blog post)关于如何最好的unique_ptr传递给构造函数,但它会是这个样子:

class House { 
private: 
    std::unique_ptr<Animal> pet_; 
public: 
    House(std::unique_ptr<Animal> pet) : pet_(std::move(pet)) {} 
}; 

我们已通过了unique_ptr到构造,并再“移动”,它给成员变量。

调用代码可能看起来是这样的:

auto pet = createPet(6.0); 
    House house(std::move(pet)); 

构建House后,pet变量会nullptr因为我们已经转移了宠物所有权有关的House

Live demo

+0

更改构造函数以获取unique_ptr的r值引用会更好吗?例如。 House(std :: unique_ptr && pet)。那么你不需要在pet_的初始化列表中使用std :: move()调用? – jfritz42 2016-11-16 00:15:21

+1

@ jfritz42一个r值引用本身就是一个l值,所以你仍然需要'std :: move'。 [试试](http://coliru.stacked-crooked.com/a/42b8222989a16651)。 – 2016-11-16 07:49:25

+0

好点!顺便说一句,这似乎是一个新的C++习惯用法。我想知道是否有任何人给出了一个名字。 “转让所有权成语”? – jfritz42 2016-11-16 19:25:24

相关问题