【问题标题】:Vector with unique_ptr-s带有 unique_ptr-s 的向量
【发布时间】:2013-03-20 04:49:11
【问题描述】:

我有这样的代码:

#include <memory>
#include <vector>

namespace daq
{

class Animal
{
public:
    Animal(){};
};

class Pig : public Animal
{
public:
    Pig() : Animal () {};
};

class Farm
{
public:
    void addAnimal(Animal& animal)
    {
        mAnimals.push_back(std::unique_ptr<Animal>(animal)); // error
    }

private:
    std::vector<std::unique_ptr<Animal>> mAnimals;
};
} /* namespace daq */

但我在方法 Farm::addAnimal: 中遇到错误:

没有匹配函数调用'std::unique_ptr::unique_ptr(daq::Animal&)'

我应该将什么传递给 push_back 方法?

【问题讨论】:

  • 你应该传递一个指针。
  • 如果你想存储通过引用收到的项目的动态副本(std::unique_ptr),你必须以某种方式使元素类型(动物)可克隆

标签: c++ c++11 move-semantics


【解决方案1】:

unique_ptr 接受 pointer 作为构造函数参数,但您传递的是 reference。这基本上是编译器告诉你的:你不能从 daq::Animal&amp; 构造 std::unique_ptr

您可以将原始指针传递给使用new 分配的Animal 类型的对象,或者(最好)您应该传递以这种方式构造的unique_ptr 并在提供时从它移开它作为push_back()的参数:

void addAnimal(std::unique_ptr<Animal>&& animal)
//                                    ^^
//                                    This is to make it absolutely clear that
//                                    your intention is to bind to an object
//                                    the client wants to move from. It is not
//                                    especially needed here (unique_ptr is not
//                                    copyable), but it makes your interface
//                                    more explicit about it. [Credits to sehe]
{
    mAnimals.push_back(std::move(animal)); // OK
}

int main()
{
    daq::Farm farm;
    std::unique_ptr<daq::Animal> pig(new daq::Pig());
    farm.addAnimal(std::move(pig)); // OK
}

您必须在此处使用std::move(),因为unique_ptrs 是不可复制的,因此您有效地将pig 的所有权从调用它的例程转移到包含它的向量(addAnimal() 是中间人)。

【讨论】:

  • 出于风格的原因,将参数“接收”为右值引用(记录移动语义)不是更好吗? void addAnimal(std::unique_ptr&lt;Animal&gt;&amp;&amp; animal);
  • @sehe:你的意思是,接收Animal&amp;&amp; 并执行farm.addAnimal(std::move(animal))
  • 我的意思是 alter 现有的addAnimal(不添加另一个重载)
  • @sehe:这就是我的意思:改变现有的addAnimal() 以接收Animal&amp;&amp;,并通过farm.addAnimal(std::move(animal)) 调用它。这是你的建议吗?
  • @sehe:这会破坏我想说的引用语义(尽管不清楚这里是否需要它)。客户可能希望保留一个指向它添加到农场的动物的观察指针。另一方面,如果不需要引用语义,那么mAnimals 可以是vector&lt;Animal&gt;addAnimal() 的参数可以完美转发到mAnimals
猜你喜欢
  • 2022-11-23
  • 1970-01-01
  • 2020-10-25
  • 2014-07-21
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
相关资源
最近更新 更多