0

In the following (borrowed) example, in my environment the move constructor is never called:

#include <iostream>

class MyClass {
  public:
      MyClass()
      {
          std::cout << "default constructor\n";
      }
      MyClass(MyClass& a)
      {
          std::cout << "copy constructor\n";
      }

      MyClass(MyClass&& b)
      {
          std::cout << "move constructor\n";
      } 
};  

void test(MyClass&& temp)
{
    MyClass a(MyClass{}); // calls MOVE constructor as expected
    MyClass b(temp); // calls COPY constructor...  
}

int main()
{
    test(MyClass{});
    return 0;
}

My output is: default constructor default constructor copy constructor

I use XCode version 9.1, shouldnt the move constructor be called on rvalue references? What am I missing here?

John.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
John Gorter
  • 2,162
  • 2
  • 17
  • 25
  • `MyClass&& temp` is actually an lvalue at the point at which you call `MyClass b(temp);` (since it has a name); In order to call the rvalue constructor you need to *move* it (`MyClass b(std::move(temp));`) – Steve Lorimer Nov 27 '17 at 20:56

1 Answers1

0

What am I missing here?

The point is that everything that has a name is lvalue.

It means that named rvalue reference itself is lvalue and temp from:

void test(MyClass&& temp)

is lvalue as well. So move constructor is not called.

If you want a move constructor to be called, use std::move:

void test(MyClass&& temp)
{
    // ...
    MyClass b(std::move(temp)); // use std::move here 
}

By the way,

 MyClass(MyClass& a)
 {
     std::cout << "copy constructor\n";
 }

is not a copy constructor because copy constructor has a form of:

MyClass(const MyClass& a) { ... }
Edgar Rokjān
  • 17,245
  • 4
  • 40
  • 67