user2138149
user2138149

Reputation: 16559

C++ Do I always have to use std::move to invoke the move constructor?

"Theory" question if you will.

In order to execute/make use of the move constructor in a class, do I always have to use std::move(...) to tell the compiler that I wish to 'move' an object rather than copy it?

Are there any cases where the compiler will invoke the move constructor for me without the use of std::move? (My guess would be in function return values?)

Upvotes: 2

Views: 439

Answers (3)

Jts
Jts

Reputation: 3527

std::move is just a cast.

unique_ptr<int> global;

auto v = unique_ptr<int>(global); // global is a lvalue, therefore the
unique_ptr(unique_ptr<T>&v) constructor that accepts lvalue references is called.

auto v = unique_ptr<int>(std::move(global)); // move returns a &&rvalue reference, therefore the
unique_ptr(unique_ptr<T>&&v) constructor that accepts &&rvalue references is used.

When the criteria for elision of a copy operation are met and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.

therefore,

unique_ptr<int> hello()
{
    unique_ptr<int> local;
    return local;

    // local is an lvalue, but since the critera for elision is met,
    // the returned object is created using local as if it was an rvalue
}

Also,

unique_ptr<int> hello = std::unique_ptr<int>();
// we have a pure rvalue in the right, therefore no std::move() cast is needed.

Upvotes: 1

Emil Laine
Emil Laine

Reputation: 42828

The compiler will invoke the move constructor without std::move when:

  • returning a local variable by value
  • when constructing an object from an rvalue of the same type

In all other cases, use std::move. E.g.:

struct S {
  std::string name;
  S(std::string name) : name(std::move(name)) {}
};

and

std::unique_ptr<Base> func() {
  auto p = std::make_unique<Derived>();
  return std::move(p); // doesn't work without std::move
}

Upvotes: 4

Michael Albers
Michael Albers

Reputation: 3779

According to cppreference.com (http://en.cppreference.com/w/cpp/language/move_constructor):

The move constructor is called whenever an object is initialized from xvalue of the same type, which includes

  • initialization, T a = std::move(b); or T a(std::move(b));, where b is of type T;
  • function argument passing: f(std::move(a));, where a is of type T and f is void f(T t);
  • function return: return a; inside a function such as T f(), where a is of type T which has a move constructor.

In most cases, yes std::move is needed.

Upvotes: 4

Related Questions