问题
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... not expected...?
}
int main()
{
test(MyClass{});
return 0;
}
For the above code, I expected both object creations in test() to call move constructor because b is a r-value reference type (MyClass&&).
However, passing b to the MyClasss constructor does not call move constructor as expected, but calls copy constructor instead.
Why does second case calls copy constructor even if the passed argument is of type MyClass&& (r-value reference)???
I am using gcc 5.2.1. To reproduce my results, you must pass -fno-elide-constructors option to gcc to disable copy elision optimization.
void test(MyClass&& temp)
{
if (std::is_rvalue_reference<decltype(temp)>::value)
std::cout << "temp is rvalue reference!!\n";
else
std::cout << "temp is NOT rvalue!!\n";
}
Above code prints out "temp is rvalue reference" even if temp is named.
temp's type is rvalue reference type.
回答1:
void test(MyClass&& temp) { MyClass a(MyClass{}); // calls MOVE constructor as expected MyClass b(temp); // calls COPY constructor... not expected...? }
That is because, temp
(since it has a name,) is an lvalue
reference to an rvalue
. To treat as an rvalue
at any point, call on std::move
void test(MyClass&& temp)
{
MyClass a(MyClass{}); // calls MOVE constructor as expected
MyClass b(std::move(temp)); // calls MOVE constructor... :-)
}
来源:https://stackoverflow.com/questions/38406675/c-move-constructor-not-called-for-rvalue-reference