Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 Move constructor optimization

I'm currently trying to get a hang of move constructor. I came upon the following (Compiled using g++ d.cpp --std=c++11 -O3)

class A {
    string _x;
public:
  A(string x) { cout << "default contrsutctor: " << x << "\n"; _x = x; }
  A(const A& other) { cout << "copy contrsutctor: " << other._x << "\n"; _x = other._x;  }
  A(A&& other) { cout << "move contrsutctor: " << other._x << "\n"; _x = other._x;  }

  A foo() {
    cout << "foo: " << _x << "\n";
    return A("foo");
  }
};

int main()
{
  A a;
  A b = a;
  b.foo();
}

I expect this to output:

default contrsutctor: a
move contrsutctor: a
foo: a
default contrsutctor: foo

However the output is:

default contrsutctor: a
copy contrsutctor: a
foo: a
default contrsutctor: foo

Why isn't the A b = a line optimized to use the move constructor? The a object is never used afterwards, so it would be safe to optimize the code to use it instead of the copy constructor.

I know I could force the move contructor to be invoked with std::move(), but I'd prefer this to happen automatically in cases like this one.

like image 888
Ákos Vandra-Meyer Avatar asked Feb 05 '26 01:02

Ákos Vandra-Meyer


1 Answers

Why isn't the A b = a line optimized to use the move constructor?

What you can do in copy constructor and move constructor could be totally different. The compiler cannot guarantee that the results of the two constructors are identical. Implementing this kind of optimization has the potential of changing the behavior of your program, which breaks the as-if rule.

You need to use std::move to cast a to A&&:

#include <utility>
int main()
{
  A a("a");
  A b = std::move(a);
  b.foo();
}

A correct implementation of the move constructor should be:

A(A&& other)
: _x(std::move(other._x))
{}

After the line A b = std::move(a);, a should be "empty". In this case, a._x will be empty. as pointed by @TonyD in the comments, a._str could be in an unspecified but valid state (move constructor of std:string). You should use a with caution after this line.

like image 115
Danqi Wang Avatar answered Feb 09 '26 00:02

Danqi Wang