一个众所周知的危险错误是,函数返回了一个局部变量的指针或引用。一旦函数栈被销毁,这个指针就成为了野指针,导致未定义行为。而左值(lvalue)和右值(rvalue)的概念,本质上,是理解“程序员可以放心使用的变量”。

空泛的讨论先到这里,先看一段会报错的代码:

#include <iostream>

using std::cout;
using std::endl; int foo(int &a) {
return a;
} int main() {
int a = ;
cout << &a << endl;
int *p = &foo(a);
}

这里,对foo(a)取地址会引起错误: "lvalue required as left operand of assignment".字面理解是,&取地址运算符只能获取左值的地址。

毫无疑问的是,foo(a)的值是存在的,是数值1。之所以报错,是因为编译器认为它不是左值,不允许程序员获取它存放的地址。

我对这点标准的理解是:

获取一个临时空间的地址通常意味着要对这块内存赋值。在C++程序中,临时空间的销毁时机是不确定(undefined)的,它随时被用于其他临时空间的存储。于是程序员不允许使用这块空间。联系之前总结的堆栈概念,可以对C++中的变量存储有更深的理解。

堆栈概念一文,我小结了C++程序中数据可以存在三个地方:

1. 函数栈,在函数体内的定义的变量

2. 堆,特别指使用new,malloc获取的内存空间

3. 静态数据区,即.data 和.bss

对于lvalue的通俗描述,是“具有确定地址的非临时对象”,而不满足lvalue定义的值均被认为是rvalue。换句话说,C++程序里面出现的值,非左即右。下面我们分析一下这三个存放数据的区域里面可以被使用的值的情况:

堆的空间上的变量完全由程序员申请和管理的,所以它们都有明确的地址,是可以放心使用的左值。

静态数据区

对于静态数据区,尽管存放的位置是固定的,但里面的数据并不能认为都是左值。主要是因为里面有“字面值”,包括const所实现的常量,即静态存储而不能被修改的值。

函数栈

当函数调用发生的时候,系统会创建函数栈,保留上下文,函数调用结束的时候,函数栈内的变量会被销毁。函数体里面定义的变量是左值,而临时变量是右值。

拓展

C++ 11标准,为了更好地利用临时变量,提出Rvalue Reference,对应的的实现是move semantics (转移语意)和Perfect Forwarding(完美转发)。对这些新特性还不了解,暂时不写。

参考:

http://www.cnblogs.com/dejavu/archive/2012/09/02/2667640.html

http://stackoverflow.com/questions/230584/where-are-variables-in-c-stored

http://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c

最新文章

  1. Unity 组件不常用知识备注
  2. 关于WM_GETTEXT的应用
  3. umeng 渠道统计 android
  4. jsp_属性范围_page
  5. Android布局_布局概述和LinearLayout布局
  6. MySQL性能监控工具-MONyog
  7. Windows编译ejabberd
  8. ES6之Promise学习与实践
  9. 在mysql 5.7中,创建表的字段名中包含双引号的时候,执行会报错
  10. python 类和元类(metaclass)的理解和简单运用
  11. 解决 flannel.1 interface state DOWN
  12. agc032
  13. 一脸懵逼学习Zookeeper(动物园管理员)---》高度可靠的分布式协调服务
  14. 执行shell文件是,提示chmod: 更改&#39;./shell1.sh&#39; 的权限: 不允许的操作。
  15. USB插入电脑的硬件检测和枚举流程
  16. .NET常用开发工具整理
  17. codeforces445A
  18. javaSE习题 第二章 基本数据类型和数组
  19. Ubuntu16.04安装tensorflow+安装opencv+安装openslide+安装搜狗输入法
  20. Piwik学习 -- 插件开发

热门文章

  1. jmeter配置、安装
  2. 老李分享:性能测试你不应该只知道loadrunner(1)
  3. 老李推荐:第8章5节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-运行测试脚本
  4. 【微信开发】PHP中奖概率经典算法实例
  5. 搞定:Enter passphrase for key提示
  6. 2017.3.12 H5学习的第一周
  7. jQuery小测的总结
  8. Linux-粘滞位的使用
  9. Python科学计算—numpy模块总结(1)
  10. 记录一个NPE问题