前言
有一节我们分析了std::bind的实现原理,本节稍作休息分析一个比较简单的std::move
原理
std::move的原理太简单了,一句话:就是把传进来的参数强转为右值引用类型。作用为调用移动构造函数,或移动赋值函数。下面通过例子和代码说明。
例子
#include <iostream>
#include <cstring>
using namespace std;
struct Thing {
Thing()
{
cout << "default construct\n";
}
// Copy operator
Thing(const Thing& other)
{
cout << "copy constructor\n";
}
// Move constructor
Thing(Thing&& other) noexcept
{
cout << "move constructor\n";
}
// assignment operator
Thing& operator=(const Thing& rhs) {
cout << "copy operator\n";
return *this;
}
// move assignment operator
Thing& operator=(Thing&& rhs) noexcept {
cout << "move operator\n";
return *this;
}
// destructor necessary since we are working in dangerous new/delete territory
~Thing() noexcept {
cout << "destructor " << "\n";
}
};
int main()
{
cout << "main::constructing a\n";
Thing a;
cout << "main::moving a to newly constructed c\n";
Thing c(std::move(a));
Thing x = std::move(c);
cout << ">main::thing y\n";
Thing y;
y = std::move(x);
return 0;
}
[mzhai@c++11]$ ./a.out
main::constructing a
default construct
main::moving a to newly constructed c
move constructor //Thing c(std::move(a));
move constructor //Thing x = std::move©;
main::thing y
default construct
move operator //y = std::move(x);
destructor
destructor
destructor
destructor
a, c, x虽然都是左值,但std::move却把它们强转成了右值引用,从而调用了move语义的函数而不是copy语义的。
std::move源码
92 /**
93 * @brief Convert a value to an rvalue.
94 * @param __t A thing of arbitrary type.
95 * @return The parameter cast to an rvalue-reference to allow moving it.
96 */
97 template<typename _Tp>
98 constexpr typename std::remove_reference<_Tp>::type&&
99 move(_Tp&& __t) noexcept
100 {
return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
让我们看看remove_reference 的定义,看看它是怎么脱去类型的外衣的:
1402 /// remove_reference
1403 template<typename _Tp>
1404 struct remove_reference
1405 {
typedef _Tp type; };
1406
1407 template<typename _Tp>
1408 struct remove_reference<_Tp&>
1409 {
typedef _Tp type; };
1410
1411 template<typename _Tp>
1412 struct remove_reference<_Tp&&>
1413 {
typedef _Tp type; };
原来不管你原来的类型是左值引用还是右值引用,统统都定义type为脱去外衣的类型。