无法理解如何将新对象添加到std :: list <std :: unique_ptr <classname>&gt; </std :: unique_ptr <classname>

时间:2014-09-29 07:09:10

标签: c++ c++11 stl unique-ptr

我对unique_ptr的std :: list有一个奇怪的问题。

类slFlyingMonster派生自类slMonster。

以下代码有效:

std::unique_ptr<slMonster> ptr(new slFlyingMonster(md));

但是这段代码:

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(new slFlyingMonster(md));

抛出错误:

  

“错误1错误C2664:'无效
  的std ::列表&gt;,的std ::分配器&GT;&GT;&GT; ::的push_back(常量   的std ::的unique_ptr&LT; _Ty,性病:: default_delete&LT; _Ty&GT;&GT; &amp;)':无法转换   参数1从'slFlyingMonster *'到   “的std ::的unique_ptr&GT; &安培;&安培;'“

虽然我明白,有些东西是错的,比如std :: list.push_back()和=不一样,但是我无法弄清楚如何正确地将新类添加为unique_ptr to list。任何建议都会非常受欢迎。

3 个答案:

答案 0 :(得分:4)

您可以使用emplace_back

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(new slFlyingMonster(md));

或push_back std::make_unique

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(std::make_unique<slFlyingMonster>(md));

std::move

std::unique_ptr
std::list<std::unique_ptr<slMonster>> mMonsters;
std::unique_ptr<slMonster> p(new slFlyingMonster(md));
mMonsters.push_back(std::move(p));

构造函数std::unique_ptr<T>(T*)是显式的,因此T*无法隐式构造std::unique_ptr

答案 1 :(得分:4)

如果您拥有列表所包含类型的对象,并且想要推送其副本,请使用push_back。通常情况下,如果您还没有这样的对象(在您的情况下,您没有),那么您最好直接在列表中初始化新对象 - 使用emplace_back代替:

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(new slFlyingMonster(md));

但是,正如@SebastianRedl在评论中正确指出的那样,上面的问题不是例外安全。如果std::list内的新节点的内部分配抛出,则新的slFlyingMonster实例将被泄露。当其中一个参数是不受保护的资源(例如拥有内存的原始指针)时,emplace_back不是正确的选择。

所以你实际上想要构造一个包装器智能指针并将其推入列表中。在C ++ 14中,您可以使用std::make_unique

执行此操作
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(std::make_unique<slFlyingMonster>(md));

使用普通的C ++ 11,您可以实现自己的make_unique,也可以显式创建智能指针:

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(std::unique_ptr<slMonster>(new slFlyingMonster(md)));

答案 2 :(得分:0)

使用mMonsters.emplace_back,以便根据参数中给出的参数创建对象。