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.

+3


source to share


3 answers


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)));

      

+4


source


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

.

+4


source


Use mMonsters.emplace_back

, so the object is created from the argument given in the parameters.

0


source







All Articles