By Dan


2019-07-07 20:37:44 8 Comments

An unique_ptr cannot be pushed back into a std::vector since it is non-copyable, unless std::move is used. However, let F be a function that returns a unique_ptr, then the operation std::vector::push_back(F()) is allowed. There is an example below:

#include <iostream>
#include <vector>
#include <memory>

class A {
  public:
    int f() { return _f + 10; }

  private:
    int _f = 20;
};

std::unique_ptr<A> create() { return std::unique_ptr<A>(new A); }


int main() {
  std::unique_ptr<A> p1(new A());

  std::vector< std::unique_ptr<A> > v;

  v.push_back(p1); // (1) This fails, should use std::move

  v.push_back(create()); // (2) This doesn't fail, should use std::move?

  return 0;
}

(2) is allowed, but (1) is not. Is this because the returned value is moved somehow implicitly?

In (2), is it actually necessary to use std::move?

4 comments

@NewMe 2019-07-08 20:30:38

It is also worth knowing that it would also work due to compiler ability to move objects that are not move explicitly (NRVO)

#include <iostream>
#include <vector>
#include <memory>

class A {
  public:
    int f() { return _f + 10; }

  private:
    int _f = 20;
};

std::unique_ptr<A> create() {
    std::unique_ptr<A> x (new A);
    return x; 

}


int main() {
  std::unique_ptr<A> p1(new A());

  std::vector< std::unique_ptr<A> > v;

  //v.push_back(p1); // (1) This fails, should use std::move

  v.push_back(create()); // (2) This doesn't fail, should use std::move?

  return 0;
}

@Kadir Erdem Demir 2019-07-07 20:56:24

With C++11 we got move constructors and rvalues semantics.

std::move(X) is just a cast to a rvalue which converts X to X&& that is it. Than move ctor takes the job over and move constructors typically "steal" the resources held by the argument. unique_ptr have a move ctor.

Function return values are already a rvalue(unless the function returns an lvalue reference as indicated by @HolyBlackCat in comments) which will trigger the move ctor without needing any extra cast. And since move ctor is defined for unique_ptr it will compile.

Also the reason why v.push_back(p1);failing is: you try to call copy constructor with an lvalue and it fails because unique_ptr does not have a copy ctor.

@Remy Lebeau 2019-07-07 21:03:42

std::vector::push_back() has an overload that takes an rvalue reference as input:

void push_back( T&& value );

The return value of create() is an unnamed temporary, ie an rvalue, so it can be passed as-is to push_back() without needing to use std::move() on it.

std::move() is needed only when passing a named variable, ie an lvalue, where an rvalue is expected.

@HolyBlackCat 2019-07-07 20:40:23

std::move(X) essentially means "here, treat X as if it was a temporary object".

create() returns a temporary std::unique_ptr<A> to begin with, so move is unnecessary.


If you want to know more, look into the value categories. Your compiler uses value categories to determine if an expression refers to a temporary object ("rvalue") or not ("lvalue").

p1 is an lvalue, and create() is an rvalue.

@ZivS 2019-07-10 04:56:10

Although true, your answer lacks the part that explains why and how push_back allows this behavior which is the part that can help people understand how they can implement and allow such code to work with their own APIs

Related Questions

Sponsored Content

19 Answered Questions

[SOLVED] How to find out if an item is present in a std::vector?

  • 2009-02-20 21:58:41
  • Joan Venge
  • 877948 View
  • 588 Score
  • 19 Answer
  • Tags:   c++ vector std

1 Answered Questions

[SOLVED] Vector push_back error when compiling

22 Answered Questions

[SOLVED] Concatenating two std::vectors

6 Answered Questions

[SOLVED] What is std::move(), and when should it be used?

4 Answered Questions

[SOLVED] std::auto_ptr to std::unique_ptr

3 Answered Questions

[SOLVED] push_back vs emplace_back to a std::vector<std::string>

0 Answered Questions

Move std::unique_ptr<int[]> to Platform::Collections::Vector<int>

1 Answered Questions

[SOLVED] Move objects from a unique_ptr array to a vector

2 Answered Questions

[SOLVED] C++ std::unique_ptr but non movable?

  • 2014-03-04 19:10:41
  • Sandu Liviu Catalin
  • 1559 View
  • 2 Score
  • 2 Answer
  • Tags:   c++ c++11 unique-ptr

1 Answered Questions

Sponsored Content