0

Sample code, C++11, -fno-elide-constructors.

#include <iostream>
#include <string>
using namespace std;

class ClassA
{
    int a, b;
public:
    ClassA() = default;
    ClassA(const ClassA &obj)
    {
        cout << "copy constructor called" << endl;
    }

    ClassA(ClassA &&obj) {
        cout << "move ctor called" << endl;
    }
};

ClassA bar(ClassA &str)
{
    return str;  //call copy ctor
}

int main()
{
    ClassA str;
    ClassA foo = bar(str); //call move ctor
    return 0;
}

https://wandbox.org/permlink/DyALfRETs2LfWSjc

Why this assignment ClassA foo = bar(str); call move ctor instead of copy ctor? Since both const lvalue reference and rvalue reference can accept rvalue.

Rick
  • 7,007
  • 2
  • 49
  • 79
  • I dont think this is a duplicated question! Firstly, `ClassA foo = bar(str)` is equivalent to `Class foo(bar(str))`; The **copy ctor** happend because your `-fno-elide-constructors`, and the variable `str` is **not** a temp object. so, if you return with `std::move(str)` it will call the **move ctor** instead. While, the **move ctor** happend because the function `bar(str)` returned a temp object. So it's not about "both const lvalue reference and rvalue reference can accept rvalue". – Wei Guo Aug 01 '18 at 08:28
  • @WeiGuo Yes, it's a duplicated one.. I got what I want from that. – Rick Aug 01 '18 at 09:03

1 Answers1

0

const lvalue reference can bind to everything, so if the compiler would favor this over the rvalue reference the move constructor would not be called ever if a copy constructor is provided, and that would defeat the purpose of having both.

The rvalue reference accepting function is a more specialized version of the more generic const lvalue reference accepting one, and the compiler always chooses the most specialized version.

Adelin
  • 7,809
  • 5
  • 37
  • 65
Petok Lorand
  • 955
  • 6
  • 15