我对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。任何建议都会非常受欢迎。
答案 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
,以便根据参数中给出的参数创建对象。