0

I tried to initialize an instance with return value of a function. I expected it will call move constructor but the result is not. It seems that the return value are directly taken over by instance t. Because the t and return value in the function are the same address. Is the complier optimize this situation?

My environment is Mac OS X mavericks, default g++ -std=c++11

class T1 {
 public:
  T1() {
    printf("T1::constructor\n");
    t = new char[100];
  }
  T1(const T1 &another) {
    printf("T1::copy_constructor\n");
  }
  T1(T1 &&another) {
    printf("T1::move_constructor\n");
  }
  char *t;
};

T1 func() {
  T1 t;
  printf("add:%d\n", static_cast<void*>(&t));
  return t;
}

void rref_test() {
  T1 t = func();
  T1 t2 = std::move(t);
  printf("add:%d\n", static_cast<void*>(&t));
}


int main() {
  rref_test();

  return 0;
}
Zhaoze
  • 1

1 Answers1

3

It depends on the return type. If the return type is an lvalue reference then the function call expression is an lvalue, otherwise it is an rvalue.

When you write T1 t = func(); , func() is an rvalue. However this situation is a candidate for copy elision which is why you do not see any copy-constructor or move-constructor calls.

For T1 t2 = std::move(t); you should see a call to the move-constructor.

Some compilers have switches to disable copy elision, e.g. with gcc it is -fno-elide-constructors.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365