概述
目录
一、右值引用
二、forward源码分析
三、示例分析
1、不使用 std::forward
2、用 std::forward
四、std::move源码
五、参考:
一、右值引用
int和int&是什么?都是类型。int是整数类型,int&则是整数引用类型。同样int&&也是一个类型。两个引号&&是C++ 11提出的一个新的引用类型,右值引用类型,这是一个新的类型。如果你记住这个新类型,那么很多疑问都能迎刃而解。void G(A &&a) ,就很容易明白a是新类型右值引用的一个变量一个值,肯定是一个左值而不是右值。
二、forward源码分析
/**
* @brief Forward an lvalue.
* @return The parameter cast to the specified type.
*
* This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
{ return static_cast<_Tp&&>(__t); }
/**
* @brief Forward an rvalue.
* @return The parameter cast to the specified type.
*
* This function is used to implement "perfect forwarding".
*/
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{
static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
" substituting _Tp is an lvalue reference type");
return static_cast<_Tp&&>(__t);
}
对于forward函数
std::forward<T>(u)有两个参数:T与 u。
a. 当T为左值引用类型时,u将被转换为T类型的左值。比如T 为int&
b. 否则u将被转换为T类型右值。比如T为 int ,int &&
三、示例分析
1、不使用 std::forward
下述代码G不管传入什么类型的参数,只会最终调用 void F(int& a);
using namespace std;
void F(int& a) {
cout << "int& version " <<a <<endl;
}
void F(int&& a) {
// do something
cout << "int&& version " <<a <<endl;
}
template<class A>
void G(A &&a) {
F(a);
}
int main (int argc, char *argv[]) {
int i = 2;
G(i); //输出int& version
G(5); //输出int& version
return 0;
}
G不管传入什么类型的参数,只会最终调用 void F(int& a)
这是为什么?
调用G(5)时,A被推导为int类型,但在G内部调用F(a)时,因为G函数中a是一个int &&的变量是个左值,调用F时编译译器自动推断调用 F(int & &&)类型的函数,根据引用折叠原理就会调用F(int & )c++引用折叠_kupePoem的专栏-CSDN博客
调用G(i)时,A被推导为int &类型,根据引用折叠原理就会调用F(int & )。
2、用 std::forward
用 std::forward时,G的最终调用出现差异化
using namespace std;
void F(int& a) {
cout << "int& version " <<a <<endl;
}
void F(int&& a) {
// do something
cout << "int&& version " <<a <<endl;
}
template<class A>
void G(A &&a) {
F(std::forward<A>(a));
}
int main (int argc, char *argv[]) {
int i = 2;
G(i); //输出int& version
G(5); //输出int&& version
return 0;
}
调用G(5)时,A被推导为int类型,但在G内部调用F(a)时,因为G函数中a是一个int &&的变量是个左值,调用std::forward<A>(a)(std::forward<int>(a)),A此时为int,强制转换为了右值。
调用G(i)时,A被推导为int &类型,调用std::forward<A>(a)(std::forward<int&>(a)),还是强制转换成了左值。
四、std::move源码
头文件move.h
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
可以看出std::move也是进行了强制类型转换,把一个左值强制转换成右值,没有新奇之处,参数__t的类型是万能引用(CSDN),可以接受不同类型的参数。
using namespace std;
void F(int& a) {
cout << "int& version " <<a <<endl;
}
void F(int&& a) {
// do something
cout << "int&& version " <<a <<endl;
}
template<class A>
void G(A &&a) {
F(std::forward<A>(a));
}
int main (int argc, char *argv[]) {
int i = 2;
G(std::move(i)); //输出int&& version
G(5); //输出int&& version
return 0;
}
五、参考:
引用折叠和完美转发 - 知乎
如何理解c++中的引用折叠? - 知乎
C++ 11 右值引用以及std::move_luotuo44的专栏-CSDN博客
一文读懂C++右值引用和std::move_kupePoem的专栏-CSDN博客
最后
以上就是幸福嚓茶为你收集整理的std::forward和std::move源码分析一、右值引用二、forward源码分析三、示例分析四、std::move源码五、参考:的全部内容,希望文章能够帮你解决std::forward和std::move源码分析一、右值引用二、forward源码分析三、示例分析四、std::move源码五、参考:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复