-
引用折叠
template <class T> void func(T && arg);
若一个右值引用(
&&
)参数被一个左值或左值引用初始化,那么引用将折叠为左值引用。(即:T&& & –> T&)int a = 1; func(a); // func()中 参数arg 变成 int &类型 int &ref = a; func(ref); // func()中 参数arg 变成 int &类型
若一个右值引用参数被一个右值初始化,那么引用将折叠为右值引用。(即:T&& && 变成 T&&)。
func(10); // func()中 参数arg 仍是 int &&类型
一个左值引用参数不管是被一个左值还是右值初始化,引用都不能折叠,仍为左值引用(即:T& & –>T&,T& && –>T&)。
-
为什么需要引入
std::forward
?有这么个例子:
template <class T> void func(T && arg){ cout << &arg; }
这个函数是可以通过编译且运行的,并且在调用时无论传入一个左值(引用)或者右值,都不影响函数将参数
arg
视作左值并取其地址。这也就说明了,一个右值引用参数在函数中使用时,依旧会被当成一个左值去使用。
另一个例子是:
template <class T> Data* func(T && arg){ return new Data(arg); }
假定有一个类
Data
,这个类中实现了复制构造和移动构造函数,倘若使用以上写法,在函数func
中,会调用Data
的复制构造函数来初始化一个Data
对象,而不是其移动构造函数。而使用
std::forward
就可以解决这个问题:template <class T> Data* func(T && arg){ return new Data(std::forward<T>(arg)); }
将参数
arg
的右值引用属性保留并作为右值引用参数传给Data
,所以称为完美转发。
C++ | 完美转发:std::forward
发布时间 2023-09-22 16:54:18作者: C111-CR