Chapter3:左值和右值
- 1. 将右值绑定到 左值
- 2. 将右值绑定到 常量左值引用
- 3. 将右值绑定到右值引用
- 总结:
- 5. 左值,右值和右值引用
- 6. 引用类型可以引用的值
在C语言中,我们常常会提起左值(lvalue),右值(rvalue)这样的称呼,而在编译程序时,编译器有时也会报出错误信息中包含 左值,右值说法。不过左值、右值通常不是通过一个严谨的定义而为人所知。下面我通过这样一个例子,来引导大家认识: 左值,右值,左值引用,右值引用,常量左值引用。
#include<iostream>
struct Copyable{
Copyable() {
std::cout<< "copied...." << std::endl;
}
Copyable(const Copyable ©)
{
std::cout<< "copied" << std::endl;
}
};
Copyable ReturnRvalue()
{
// 这是返回的 右值
return Copyable();
}
// 1. 接收右值表达式
void AcceptValue(Copyable copy)
{
}
// 2. 右值引用减少对象开销,并延迟对象生命周期
// 直观意义:为临时变量续命,也就是为右值续命,因为右值在表达式结束后就消亡了,
// 如果想继续使用右值,那就会动用昂贵的拷贝构造函数。
void AcceptRef(Copyable && copy)
{
}
// 3. 常量左值引用减少对象开销,并延迟对象生命周期
void AcceptRef_2(const Copyable& copy){}
int main()
{
Copyable copy;
std::cout << "Pass by value:" << std::endl;
AcceptValue(ReturnRvalue());
std::cout << "Passs by reference: " << std::endl;
AcceptRef(ReturnRvalue());
std::cout << "Passs by reference_2: " << std::endl;
AcceptRef(ReturnRvalue());
}
// 打印结果:
copied.....
Pass by value:
copied.....
Passs by reference:
copied.....
Passs by reference_2:
copied.....
上面的例子:我们用到了
- 函数形参为左值,然后将右值表达式作为实参绑定到左值
- 函数形参为右值引用,然后将右值作为实参绑定右值引用
- 函数形参为常量左值引用,然后将右值作为实参绑定到 常量左值引用
1. 将右值绑定到 左值
💚💚 这种绑定方式的特点:
- 函数 ReturnRvalue() 在运行结束后,返回值(右值临时变量)复制一份作为实参传递给 AcceptValue() 函数后就不会存活下去了。
这样会导致:Copyable 这个对象构建两次。浪费内存。
2. 将右值绑定到 常量左值引用
💚💚
- AcceptRef使用了引用传递,在 以 ReturnRvalue 返回的右值为参数的时候,AcceptRef 就可以直接使用产生的临时值(并延长其生命周期)。
- 这个临时值的生命周期就和 AcceptRef() 生命周期一致
3. 将右值绑定到右值引用
💚💚
- AcceptRef使用了引用传递,在 以 ReturnRvalue 返回的右值为参数的时候,AcceptRef 就可以直接使用产生的临时值(并延长其生命周期)。
- 这个临时值的生命周期就和 AcceptRef() 生命周期一致。
总结:
🧡 通过上面三个小节,我们总结了 将右值绑定到 :左值,常量左值引用,右值引用的情况,下面以这个为例子,分析左值、右值含义,通常情况下,哪些是左值哪些是右值。