当前位置: 代码迷 >> 综合 >> C++11中的 std::move 右值引用转换实现原理
  详细解决方案

C++11中的 std::move 右值引用转换实现原理

热度:52   发布时间:2023-12-12 16:17:59.0

1. 从一个简单的例子开始

我们看一个例子,研究一下 C++ 是如何判断参数是左值引用还是右值引用的。

#include <iostream>
using namespace std;void print(int& x){
    cout << "x is int&" << endl;
}void print(int&& x){
    cout << "x is int&&" << endl;
}int main(){
    int x = 0;print(x);				\\x is int&print(0);				\\x is int&&print(std::move(x));	\\x is int&&return 0;
}

运行结果如下:

x is int&
x is int&&
x is int&&

2. std::move 原理分析

那么,std::move 到底做了什么工作,把本应该是左值引用的变量 x 硬生生改成了右值引用?我把 STL 和 move 函数有关的源代码汇总如下:

#define _NOEXCEPT throw ()// TEMPLATE remove_reference
template<class _Ty>struct remove_reference{
    	// remove referencetypedef _Ty type;};// TEMPLATE FUNCTION move
template<class _Ty> inlinetypename remove_reference<_Ty>::type&&move(_Ty&& _Arg) _NOEXCEPT{
    	// forward _Arg as movablereturn ((typename remove_reference<_Ty>::type&&)_Arg);}

在我们的例子中,x 的数据类型是 int,下面的代码按照 STL 定义方式展开后到底是什么样子的。

int x;
move(x);

首先看template struct remove_reference,实际上 _Ty 就是 int,于是我们得到:

typename remove_reference<_Ty>::type    ====〉  int

用 x 取代 _Arg,于是上面那一大坨代码就简化成了:

	int&& move(int&& x) {	return (int&&) x;}

我靠,本来以为有很复杂的技巧,原来就这么简单。move 的输入参数定义保证了输入参数 x 只能是右值引用,然后原样返回输出即可。

3. 自己写一个 move 函数试试

把开始的例子改写了一下,非常OK!

#include <iostream>
using namespace std;void print(int& x){
    cout << "x is int&" << endl;
}void print(int&& x){
    cout << "x is int&&" << endl;
}int&& move(int&& x){
    return (int&&)x;
}int main(){
    int x = 0;print(x);print(0);print(move(x));return 0;
}

本质上,std::move(x) 返回了变量的右值引用指针,移交给第三方随意处置。这意味着,x 在被使用之后,生命周期就结束了,之后任何对 x 的使用都是不可靠的。

把一个变量以右值引用方式传递给一个函数,等于对这个函数说,这是本变量最后一次为别人提供服务,你可以对我随意处置,之后不会再有任何地方会引用我的内容,我随时可能被析构掉。

  相关解决方案