无法理解如何向std :: list <std :: unique_ptr <classname >>添加新对象

Sta*_*ght 4 c++ stl unique-ptr c++11

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

slFlyingMonster类是从slMonster类派生的。

以下代码有效:

std::unique_ptr<slMonster> ptr(new slFlyingMonster(md));
Run Code Online (Sandbox Code Playgroud)

但是这段代码:

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(new slFlyingMonster(md));
Run Code Online (Sandbox Code Playgroud)

引发错误:

“错误1错误C2664:'void
std :: list>,std :: allocator >>> :: push_back(const std :: unique_ptr <_Ty,std :: default_delete <_Ty >>&)':无法从'slFlyingMonster *'到'std :: unique_ptr> &&'“

据我了解,这是错误的,例如std :: list.push_back()与=不同,但是我无法弄清楚如何正确地将新类作为unique_ptr添加到列表中。任何建议将非常欢迎。

Jar*_*d42 5

您可以使用emplace_back

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(new slFlyingMonster(md));
Run Code Online (Sandbox Code Playgroud)

或 push_back a std::make_unique

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(std::make_unique<slFlyingMonster>(md));
Run Code Online (Sandbox Code Playgroud)

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));
Run Code Online (Sandbox Code Playgroud)

构造函数std::unique_ptr<T>(T*)explicit,因此T*不能隐式构造 a std::unique_ptr


Rei*_*ica 5

使用push_back时,你有,你的列表中包含的类型的对象,你想要把它的拷贝。通常,如果您还没有这样的对象(就您的情况而言,则没有),那么最好直接在列表中初始化一个新对象-使用emplace_back

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(new slFlyingMonster(md));
Run Code Online (Sandbox Code Playgroud)

但是,正如@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));
Run Code Online (Sandbox Code Playgroud)

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

std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(std::unique_ptr<slMonster>(new slFlyingMonster(md)));
Run Code Online (Sandbox Code Playgroud)