C++ 左值右值引用梳理
C++ 左值右值引用梳理
左值与右值的区别
在参考资料上看到这样一句话
https://www.internalpointers.com/post/understanding-meaning-lvalues-and-rvalues-c
In C++ an lvalue is something that points to a specific memory location. On the other hand, a rvalue is something that doesn’t point anywhere. In general, rvalues are temporary and short lived, while lvalues live a longer life since they exist as variables. It’s also fun to think of lvalues as containers and rvalues as things contained in the containers. Without a container, they would expire.
总的来说,左值可以获取地址,而右值不能。lvalue指的是可以放在赋值表达式左边的事物——在栈上或堆上分配的命名对象,或者其他对象成员——有明确的内存地址。rvalue指的是可以出现在赋值表达式右侧的对象——例如,文字常量和临时变量。
同样的,在《现代C++语言核心特性解析》中有这句话:
在C++中所谓的左值一般是指一个指向特定内存的具有名称的值(具名对象),它有一个相对稳定的内存地址,并且有一段较长的生命周期。而右值则是不指向稳定内存地址的匿名值(不具名对象),它的生命周期很短,通常是暂时性的。基于这一特征,我们可以用取地址符&来判断左值和右值,能取到内存地址的值为左值,否则为右值。
右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。左值可以在左边也可以在右边,右值只能在右边,举例说明
int x = 666; // ok
int* y = &x; // ok
666 = y; // error!
这里666是一个右值;一个字面常量,没有特定的内存地址。这个数字被分配给x,这是一个变量。一个变量有一个特定的内存位置,所以它是一个左值。C++声明赋值需要左值作为其左操作数。
第二句话,通过取地址运算符&将x的地址取出,&x是一个临时变量,是一个右值。
第三句话,666是一个右值,不能放在左边。
返回左值和右值的函数
对比这两个例子
int setValue()
{return 6;
}// ... somewhere in main() ...setValue() = 3; // error!
第一个例子,setValue()返回一个右值(临时数字6),它不能是赋值的左操作数。
int global = 100;int& setGlobal()
{return global;
}// ... somewhere in main() ...setGlobal() = 400; // OK
第二个例子,setGlobal返回一个引用,不像上面的setValue()。
参考链接:
【C 语言】变量本质 ( 变量概念 | 变量本质 - 内存空间别名 | 变量存储位置 - 代码区 | 变量三要素 )
关于引用为什么可以做左值,可以参考:,其实你看底层,就是指针的简化,理解后就可以明白为什么可以做左值。
从外到内理解c++引用,一文清晰解读。
C++引用在本质上是什么,它和指针到底有什么区别?
左值引用和右值引用的区别
左值引用
顾名思义,左值引用就是给左值的引用,给左值取别名。右值引用就是对右值的引用,给右值取别名。而C++11中新增了的右值引用语法特性。
在赋值运算符左侧是左值引用符,右侧必须是左值;在赋值运算符左侧是右值引用符,右侧必须是右值。
看下面的例子:
int y = 10;
int& yref = y;
yref++; // y is now 11
int& yref = 10; // wrong
void fnc(int& x)
{
}int main()
{fnc(10); // Nope!// This works instead:// int x = 10;// fnc(x);
}
但是下面的例子成功:
void fnc(const int& x)
{
}int main()
{fnc(10); // OK!
}
更新到这里,下次再补充。