首先先描述一下C++中各种类型的值(以下无特殊说明“类型”皆按如下分法)
lvalue(left value)左值:有标识符,且不能被回收
rvalue(right value)右值:有无标识符皆可,可以被回收
glvalue(generalized left value)泛左值:有标识符,可不可被回收皆可
prvalue(pure right value)纯右值:没有标识符,且可以被回收
xvalue - X值:有标识符,且可以被回收
(还有一些特殊的类型,不过对理解forward帮助不大)
当存在fn(X &); fn(X &&);fn(const X&);几种函数定义时,编译器会根据传入值所属的类型传给对应的函数执行:
左值(非const)优先找fn(X &),若没有找到,则再寻找fn(const X&),若还没有则报错
右值类似,优先找fn(X &&),其次fn(const X&)
const左值则只能找fn(const X&)
struct X {};
// overloads
void fn(X &) { std::cout<< "X &\n"; }
void fn(const X &) { std::cout<< "const X &\n"; }
void fn(X &&) { std::cout<< "X &&\n"; }
int main()
{
X a;
fn(a);
// lvalue selects fn(X &)
// fallbacks on fn(const X &)
const X b;
fn(b);
// const lvalue requires fn(const X &)
fn(X());
// rvalue selects fn(X &&)
// and then on fn(const X &)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
还存在其他的情况没有完全列出,总之编译器会根据值的类型根据参数值类型按一定规则寻找相应的函数执行
到了模板这里也有类似的情况:
template<typename T>
void foo(T &&); // forwarding reference here
// T is a template parameter for foo
1
2
3
如果这样定义一个模板,根据传入的参数的类型不同,会调用不同的模板实例进行计算,如传入左值则调用foo(T&);传入右值则调用foo(T&&);
而forward主要解决了这样的一个问题:
右值引用作为一种引用,也是一个左值
如果一个函数接受的是T&&这种参数,在该函数体内如果希望用接收到的这个右值引用参数去调用另一个需要右值引用参数的函数是调用不到的,比如:
void reference(int& v) {
std::cout <<"lvalue" << std::endl;
}
void reference(int&& v) {
std::cout <<"rvalue" << std::endl;
}
template <typename T>
void pass(T&& v) {
reference(v);
}
int main() {
std::cout <<"rvalue pass:";
pass(1);
std::cout <<"lvalue pass:";
int p = 1;
pass(p);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
输出为:
rvalue pass:lvalue
lvalue pass:lvalue
1
2
在pass(1)的情况下,pass(T&& v)被实例化为pass(int&& v),在pass函数内用这个右值引用(类型为左值)只能调用到reference(int& v),右值引用本身是一个左值
修改代码为:
template <typename T>
void pass(T&& v) {
reference(std::forward<T>(v));
}
1
2
3
4
用forward()就能将右值引用(一个左值)转换为右值(xvalue)
forward能够将右值引用和左值引用(均为lvalue)区分出来(利用引用折叠的机制),然后相应地调用static_cast<T&>()转换为lvalue,或static_cast<T&&>()转换为rvalue
参考文章:C++ std::move and std::forward
————————————————
版权声明:本文为CSDN博主「MCCreeper」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/MCCreeper/article/details/129145074
标签:std,const,右值,完美,左值,&&,转发,forward,fn From: https://www.cnblogs.com/im18620660608/p/17364971.html