Can't figure out how to add a new object to std :: list <std :: unique_ptr <file name >>
I have a strange problem with std :: list unique_ptr.
The slFlyingMonster class is derived from the slMonster class.
The following code works:
std::unique_ptr<slMonster> ptr(new slFlyingMonster(md));
But this code:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(new slFlyingMonster(md));
raises an error:
"Error 1 error C2664: 'void
std :: list>, std :: allocator →> :: push_back (Const std :: unique_ptr <_Ty, std :: default_delete <_Ty → &)': cannot convert argument 1 from ' slFlyingMonster * 'to' std :: unique_ptr> & '"
Although I understand that something is wrong like std :: list.push_back () is not the same as =, but I cannot figure out how to properly add a new class as unique_ptr to the list. Any suggestions would be greatly appreciated.
source to share
Use push_back
when you have an object of the type that is in your list and you want to push a copy of it. Usually, if you don't already have such an object (in your case it doesn't), you'd be better off initializing the new object directly in the list - using emplace_back
instead:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(new slFlyingMonster(md));
However, as @SebastianRedl correctly pointed out in the comments, the above has the problem of not being exception safe. If the inner allocation of a new node inside is std::list
thrown away, the new instance slFlyingMonster
will leak out. emplace_back
is not the correct choice if one of the arguments is an unprotected resource (for example, raw pointer memory).
So, you really want to build a wrapper smart pointer and insert it into the list. In C ++ 14, you can do it with std::make_unique
:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(std::make_unique<slFlyingMonster>(md));
With plain C ++ 11, you can either implement your own make_unique
or create a smart pointer explicitly:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(std::unique_ptr<slMonster>(new slFlyingMonster(md)));
source to share
You can use emplace_back
:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.emplace_back(new slFlyingMonster(md));
or push_back a std::make_unique
:
std::list<std::unique_ptr<slMonster>> mMonsters;
mMonsters.push_back(std::make_unique<slFlyingMonster>(md));
or 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));
The constructor std::unique_ptr<T>(T*)
is explicit, so T*
it cannot implicitly construct a std::unique_ptr
.
source to share
Use mMonsters.emplace_back
, so the object is created from the argument given in the parameters.
source to share