1

I'm trying to initailise a vector of unique_ptr using an initialiser list and it fails with a compiler error. Which seems odd as it looks similar to a number of examples that I've seen.

std::vector<std::unique_ptr<std::string>> v{
    std::unique_ptr<std::string>{new std::string{"foo"}}
};

Fails with a compiler error.

.../memory:1645:31: error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<std::__1::basic_string<char>, std::__1::default_delete<std::__1::basic_string<char> > >'
        ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
...
...47: note: in instantiation of member function 'std::__1::vector<std::__1::unique_ptr<std::__1::basic_string<char>, std::__1::default_delete<std::__1::basic_string<char> > >, std::__1::allocator<std::__1::unique_ptr<std::__1::basic_string<char>, std::__1::default_delete<std::__1::basic_string<char> > > > >::vector' requested here
std::vector<std::unique_ptr<std::string>> v{
                                          ^
T.C.
  • 133,968
  • 17
  • 288
  • 421
Michael Barker
  • 14,153
  • 4
  • 48
  • 55

1 Answers1

0

std::unique_ptr has no copy constructor. You create an instance and then ask the std::vector to copy that instance during initialisation.

error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr<std::__1::basic_string<char>, std::__1::default_delete<std::__1::basic_string<char> > >'
        ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);

The class satisfies the requirements of MoveConstructible and MoveAssignable, but not the requirements of either CopyConstructible or CopyAssignable.

The following works with the new emplace calls. However fails to utilise initialisation lists.

std::vector< std::unique_ptr< std::string > > v;
v.emplace_back( new std::string{ "foo" } );

See using unique_ptr with standard library containers for further reading.

Ben Crowhurst
  • 8,204
  • 6
  • 48
  • 78
  • Just be aware that `emplace_back` can be used to add multiple elements, which is not exception safe when you use multiple `new` expressions. – Jens Sep 16 '15 at 07:40
  • @Jens Even this `emplace_back` is not safe. If the vector reallocates, and the reallocation throws, the pointer is leaked. – T.C. Sep 16 '15 at 08:24