在没有移动构造函数的情况下移动对象
Move object without a move constructor
再说一遍,相关问题没有回答我的问题
标准很明确:
12.8 Copying and moving class objects,
§9
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
— X does not have a user-declared copy constructor,
— X does not have a user-declared copy assignment operator,
— X does not have a user-declared move assignment operator,
— X does not have a user-declared destructor, and
— the move constructor would not be implicitly defined as deleted.
[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note ]
所以,在注意到最后的 "Note" 之前,我预计这段代码会编译失败(虽然我知道,移动 应该 回退到复制) :
#include <iostream>
using std::cout;
class c
{
public:
c() { cout << "c::c()\n"; }
c( std::initializer_list< int > ) { cout << "c::c( std::initializer_list )\n"; };
c( const c& ) { cout << "c::c( const c& )\n"; }
c& operator=( const c& ) { cout << "c& c::operator=( const c& )\n"; return *this; }
~c() { cout << "c::~c()\n"; }
void f() {}
};
void f( c&& cr ) { cout << "f()\n"; cr.f(); }
int main()
{
c x;
f( std::move( x ) );
return 0;
}
然后看到最后的注释,还是很惊讶,上面的代码输出:
c::c()
f()
c::~c()
注意 "missing" c::c( const c& )
。然后我添加了
c( c&& ) = delete;
c& operator=( c&& ) = delete;
结果还是一样
我在这里想念什么?
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
编译器标志:-s -O0 -march=native -pthread -std=c++11 -Wall -Wextra -DNDEBUG
.
您没有移动任何对象。
std::move
其实挺迷惑的,因为它什么都没动。只有移动构造函数或移动赋值运算符可以移动对象,std::move
所做的只是将左值引用 (&
) 转换为右值引用 (&&
)。
移动构造函数或移动赋值运算符可以绑定到 r-value-refernce(&&
) 并窃取对象内容。
您的示例中的 cr
参数是右值 reference。参考词在这里很重要。它的行为有点类似于我们从 c++ 中知道的平面旧引用,在 c++11 出现在游戏中之前,就它不调用任何构造函数而言......它只是 "pointing" 到你的对象通过...
要调用移动构造函数(或进行其他交换)并使用引用,我们需要进一步转发引用,例如如下:
void f( c&& cr ) {
c cr2(std::move(cr));
}
再说一遍,相关问题没有回答我的问题
标准很明确:
12.8 Copying and moving class objects,
§9
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
— X does not have a user-declared copy constructor,
— X does not have a user-declared copy assignment operator,
— X does not have a user-declared move assignment operator,
— X does not have a user-declared destructor, and
— the move constructor would not be implicitly defined as deleted.
[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note ]
所以,在注意到最后的 "Note" 之前,我预计这段代码会编译失败(虽然我知道,移动 应该 回退到复制) :
#include <iostream>
using std::cout;
class c
{
public:
c() { cout << "c::c()\n"; }
c( std::initializer_list< int > ) { cout << "c::c( std::initializer_list )\n"; };
c( const c& ) { cout << "c::c( const c& )\n"; }
c& operator=( const c& ) { cout << "c& c::operator=( const c& )\n"; return *this; }
~c() { cout << "c::~c()\n"; }
void f() {}
};
void f( c&& cr ) { cout << "f()\n"; cr.f(); }
int main()
{
c x;
f( std::move( x ) );
return 0;
}
然后看到最后的注释,还是很惊讶,上面的代码输出:
c::c()
f()
c::~c()
注意 "missing" c::c( const c& )
。然后我添加了
c( c&& ) = delete;
c& operator=( c&& ) = delete;
结果还是一样
我在这里想念什么?
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
编译器标志:-s -O0 -march=native -pthread -std=c++11 -Wall -Wextra -DNDEBUG
.
您没有移动任何对象。
std::move
其实挺迷惑的,因为它什么都没动。只有移动构造函数或移动赋值运算符可以移动对象,std::move
所做的只是将左值引用 (&
) 转换为右值引用 (&&
)。
移动构造函数或移动赋值运算符可以绑定到 r-value-refernce(&&
) 并窃取对象内容。
您的示例中的 cr
参数是右值 reference。参考词在这里很重要。它的行为有点类似于我们从 c++ 中知道的平面旧引用,在 c++11 出现在游戏中之前,就它不调用任何构造函数而言......它只是 "pointing" 到你的对象通过...
要调用移动构造函数(或进行其他交换)并使用引用,我们需要进一步转发引用,例如如下:
void f( c&& cr ) {
c cr2(std::move(cr));
}