7

After trying to write an example regarding move constructors, I ran into the following code:

#include <utility>
#include <iostream>

using namespace std;

class Data
{
public:
    Data()
    : x (3)
    {
        cout << "Data()" << endl;
    }
    Data(Data&&)
    : x(4)
    {
        cout << "Data(&&)" << endl;
    }

int x;
};

int main()
{
    Data a;
    Data b (std::move(a));
    cout << b.x << endl;
    return 0;
}

Why is the move constructor not called here? The program prints:

Data()

3

What I'm finding even weirder is that by adding a copy constructor, suddenly, it does call the move constructor...

    Data(const Data&)
    : x(2)
    {
        cout << "Data(copy)" << endl;
    }

And now it will print

Data(&&)

4

P.S I'm using gcc 4.4.5

Community
  • 1
  • 1
user1708860
  • 1,683
  • 13
  • 32
  • 1
    Strange... I'm under ubuntu, GCC 4.8. It calls the move constructor. What compiler are you using? – Paolo M Apr 20 '15 at 12:15
  • 1
    Same here (move constructor is called properly), with gcc 4.7.2. – CAdaker Apr 20 '15 at 12:17
  • 4
    It [does](https://ideone.com/CS5LC3) get called. What's your compiler and which version? – edmz Apr 20 '15 at 12:18
  • I suspect it is a microsoft compiler, is it? – GreenScape Apr 20 '15 at 12:20
  • 1
    @GreenScape I don't think so, VC11 behaves properly in this case. – Mateusz Grzejek Apr 20 '15 at 12:22
  • 2
    This question looks bogus. The purported output cannot be the actual output: There are no blank lines generated by the code, and the second output block is missing the output from the default constructor, which would surely be there. It looks too much like a hand-typed copy of something half-remembered than actual output for this to allow a meaningful analysis. – Kerrek SB Apr 20 '15 at 12:25
  • compiling using gcc 4.4.5, after seeing these comments i suspect it's a bug under this specific version – user1708860 Apr 20 '15 at 12:25
  • @KerrekSB, You are correct, it is manually copied from another computer which is not connected to the internet, but this is the actual code, I can't find any differences. – user1708860 Apr 20 '15 at 12:26
  • 2
    gcc 4.4.5 was released in October 2010, well before the final version of the C++11 specification. I wouldn't expect it to be completely conforming. – cfh Apr 20 '15 at 12:32

2 Answers2

9

Well, your code works properly for me. See this sample.

Output:

Data()
Data(&&)
4

As standard says:

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.

And

std::move obtains an rvalue reference to its argument and converts it to an xvalue.

I see no reason for behavior you describe. Perhaps there is something wrong with your compiler?


EDIT

It seems, that it is indeed the fault of the compiler. Definition of move functions was described in proposal N3053 ("Defining Move Special Member Functions"). As we can see in table on this page:

enter image description here

Mateusz Grzejek
  • 11,698
  • 3
  • 32
  • 49
3

Your code is well-formed and should call the move constructor. However, gcc 4.4, does not support defining move functions as stated here.

You do want to consider to update your compiler.

edmz
  • 8,220
  • 2
  • 26
  • 45