4

I have a vector like this:

std::vector<std::unique_ptr<Service> > m_vec;

I can run push_back like this:

m_vec.push_back(std::make_unique<Service>());

But when I run it like this:

std::unique_ptr<Service> pt = std::make_unique<Service>();
m_vec.push_back(pt);

I got error no matching function for call to ‘std::vector<std::unique_ptr<Service> >::push_back(std::unique_ptr<Service>&)

Does & mean that I'm pushing a reference to the vector? If so, why can't I push a reference?

user4016367
  • 431
  • 2
  • 9
  • 22
  • Your second example tries to make a *copy* of `pt`, which isn't going to work as `unique_ptr`'s copy constructor is deleted. – user657267 Apr 17 '16 at 13:09
  • Another duplicate: [What is the correct usage of std::unique_ptr while pushing into std::vector](http://stackoverflow.com/q/14484183/514235). – iammilind Apr 17 '16 at 13:18

2 Answers2

6

std::unique_ptr couldn't be copied, only can be moved.

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

std::make_unique<Service>() is a temporary variable and could be taken as rvalue and to be moved, but you can not do the same thing with a named variable. You can use std::move:

std::move is used to indicate that an object t may be "moved from"

Such as,

m_vec.push_back(std::move(pt));
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • thanks for the answer, if I call move, do I still be able to reuse pt? Or it doesn't exist any more? – user4016367 Apr 17 '16 at 13:26
  • @user4016367 It dpends on what do you mean "reuse pt", after moved, the ownership has been transfered from `pt` to the element of `m_vec`, it doesn't own anything. – songyuanyao Apr 17 '16 at 13:30
  • I want m_vec also keep the ownership, how to do it? – user4016367 Apr 17 '16 at 13:33
  • @user4016367 You couldn't, `unique_ptr` is unique, the ownership couldn't be shared. You might want `shared_ptr`, which retains shared ownership of an object through a pointer. – songyuanyao Apr 17 '16 at 13:36
1

what you want is

std::unique_ptr<Service> pt = std::make_unique<Service>();
m_vec.emplace_back(std::move(pt));

you cannot copy unique_ptr, since they are unique. you can create one and then move it around. emplace_back will make sure that no temporeries are made, and the element is constructed in-place(without copies, temporeries etc.)

David Haim
  • 25,446
  • 3
  • 44
  • 78