std::move()与std::forward()探究
move与forward函数探究
详情参见书《C++ primer》P608-P614
1.std::move()
copy
- 1
- 2
- 3
- 4
- 5
- 6
- 7
template<typename T>
typename std::remove_reference<T>::type&& move(T&& t)
{
return static_cast<typename std::remove_reference<T>::type&&>(t);
}
从上述std::move()
代码可以看到,该函数为一个模板。可以接受任何类型的参数,返回传入值的右值引用。
-
函数内容分析
-
typename remove_reference<T>::type
中的typename
是显式的告诉编译器这是一个类型,因为C++默认通过域作用符访问的名字不是类型。remove_reference
在头文件type_traits
中,返回T的原始类型,可参考网址。属于模版元编程范围,在编译期执行,非运行期。
copy- 1
- 2
- 3
- 4
- 5
//在编译期执行 结果都是int类型 std::remove_reference<int>::type std::remove_reference<int&>::type std::remove_reference<int&&>::type std::remove_reference<const int&>::type
-
static_cast
转换成指定的右值引用类型。可以将一个左值强制转换成右值引用。
-
-
如何工作:
- 因为参数是一个右值引用类型,所以可以传递一个右值。如
string s1 = std::move(string("hello"))
,T就会被推断为string
- 当传入一个左值时,如
string s2 = std::move(s1)
,T会被推断为string &
,函数参数t
就会推断为string& &&
类型,根据引用折叠规则,t 最终为string &
类型。注意,赋值之后s1的值是不确定的。- 当将一个左值传递给函数的右值引用参数时,且此右值引用指向为模板类型参数(T&&)时,编译器会推断模板类型参数为实参的左值引用类型
- 因为参数是一个右值引用类型,所以可以传递一个右值。如
-
模板参数类型的引用折叠:当我们使用类型别名或模板类型参数间接(不能直接)创建一个引用的引用时,会发生折叠。
- 只有右值引用的右值引用会折叠成右值引用,其他全折叠成左值引用。
- T& &, T&& &, T& && 都折叠成 T&。
- T&& && 折叠成 T&&。
-
模版元编程(template metaprogram),是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序。
- 不同于普通的运行期程序,模版元程序的执行完全是在编译期。
- 模版元程序操纵的数据不能是运行时变量,只能是编译期常量,不可修改。
- 用到的语法元素也是相当有限,不能使用运行期的一些语法,比如if-else、for等语句都不能用。
2.std::forward()
- 在某些情况下,需要将一个或者多个实参连同类型不变地转发给其他函数,需要保持被转发实参的所有性质,包括是否是const以及是左值还是右值。实现完美转发。
- 必须显示模板实参来调用。
copy
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
template <typename T>
T&& forward(typename std::remove_reference<T>::type& param)
{
return static_cast<T&&>(param);
}
template <typename T>
T&& forward(typename std::remove_reference<T>::type&& param)
{
return static_cast<T&&>(param);
}
-
有两个函数模板,接受左值就返回左值,接受右值就返回右值。
-
当param为左值引用时,调用第一个函数,推导得
T = X&
则T&&
展开为X& &&
,经过引用折叠后得到X&
,将返回左值引用即最后返回static_cast<X&>(param)
。 -
当param为左值时,调用第一个函数,T 就是普通(非引用)类型
T = X
,将返回右值引用即最后返回static_cast<X&&>(param)
。此时作用类似std::move()
,但与move函数不建议使用原对象不同,可以继续使用。 -
当param是右值引用时,调用第二个函数,此时推到得到
T = X&&
,则T&&
展开为X&& &&
,经过引用折叠后得到X&&
,将返回右值引用即最后返回static_cast<X&&>(param)
。 -
当param是右值时,调用第二个函数,T 就是普通(非引用)类型
T = X
,将返回右值引用即最后返回static_cast<X&&>(param)
。
本文作者:oniisan
本文链接:https://www.cnblogs.com/oniisan/p/moveFunction.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步