1.3变量、初始化与赋值初探
2016-08-20 10:13
106 查看
变量
一个例如x=5的语句意义已经显而易见:将5分配给x,那么我们要问了,x是什么?x就是我们所说的变量。C++中,变量的实质是一块用于存储信息的内存区域的名称,你可以把它想成一个邮箱,或者一间小屋,可以存放或取回信息。所有的电脑都有内存,称为随机存取存储器(RAM,randomaccess memory),供程序使用。当定义一个变量时,一块内存就会被留出来使用。
这一节,我们暂时只考虑整型变量,即一个拥有整数值的变量。通常我们使用一个声明语句来定义变量,下面的例子定义了一个整型变量。
[code]int x;
[/code]
当CPU执行这个语句时,RAM中的一块内存就会被预留出来(称为实例化instantiation)。比如,变量x被分配的内存位置为140,那么每当程序在表达式或者语句中看到x时,就会知道要去140位置寻找x的值。
对变量的最常见操作是赋值,赋值需要使用赋值操作符,即大家熟知的“=”符号。例如:
[code]x = 5;
[/code]
当CPU执行这个语句时,它被翻译为“将5放到内存区域140中”。
我们的程序接下来会用std::cout把这个值打印到屏幕上。
[code]std::cout << x; // 把x的值打印到屏幕上
[/code]
左值与右值
C++中变量是一种左值(l-value),左值是一种可寻址的值(a value that has an address (inmemory),看英文意义更明了)。由于所有的变量都有地址,所以所有的变量都是左值,称为左值是因为左值是唯一能够放在赋值操作符左边的值。做赋值运算时,赋值运算符的左边必须是一个左值。因此,语句5=6;将产生一个一个编译错误,因为5不是一个左值。5没有相应的内存区域,因此没有什么可以被分配给它。5就是5,它的值不能被重新分配。当一个值被分配给左值时,左值所在内存地址的值就会被重写。左值对应的为右值,右值是指任何可以被分配给左值的值,右值的计算值通常为一个单一数字。右值可以是数字5(值为5),或者一个变量x(值为最后被分配的值),或者一个表达式x+2(值为x加2)。下面是几个展示右值是如何求值得例子。
[code]int y; // 定义整型变量y y = 4; // 4的值为4,被分配给y y = 2 + 5; // 2 + 5的值为7,被分配给y,之前的y值被覆盖 int x; // 定义整型变量x x = y; // y的值为7,被分配给x x = x; // x的值为7,被分配给x(无用的语句) x = x + 1; // x+1的值为8,被分配给x,所以最终y的值为7,x的值为8
[/code]
我们来看一下上面的最后一个语句,这句是最会造成困惑的。
[code]x = x + 1 ;
[/code]
这个语句中,x被使用在两种环境中,在赋值运算符“=”左边,作为左值(在内存中有相应地址的变量),在“=”右边,作为右值,被用来产生一个具体值(此例中为7)。即:
[code]x = 7 + 1;
[/code]
这样看就很明显了,将8分配给x。
程序员是不经常谈论左值右值得,所以也没有必要过于深究。记住关键的就好,等号左边的值必须能够代表一段内存地址(比如变量),右边的值必须有特定的计算值。
赋值与初始化
初学者会遇到两个经常混淆的概念,赋值和初始化。变量被定义后,可能会通过“=”号被分配一个值(赋值)。
[code]int x;
x = 5; //此为赋值
[/code]
C++允许在定义变量的同时给予其一初始值,这称为初始化。
[code]int x = 5;
[/code]
显而易见,变量在初始化之前必须定义。
虽然这两个概念在本质上相似的,并且达成相似的目标。但在未来的课程中,我们会遇到某些类型大的变量只允许初始化,不允许赋值,所在区分一下两者还是有意义的。
未初始化的变量
与一些编程语言不同,C/C++在声明变量的同时不会自动给其赋值(比如赋0值)(这是出于性能的考量),所以当一个变量被分配到内存中的某个区域时,其默认值将该区域已有的任何可能的值,一个未被赋值的变量称为未初始化变量。注:某些编译器,比如VisualStudio,在调试模式下会自动初始化内存中的内容,在发布模式下则不会。
未初始化的变量可能产生一些有趣的(意料不到的)现象,我们来看下面这个小程序:
[code]// #include "stdafx.h" // Visual Studio用户无需注释掉此代码 #include int main() { int x; // 危险的操作,因为x未初始化 std::cout << x; return 0; }
[/code]
此例中计算机会将一些闲置的内存分配给x,然后将该区域存放的值发送给屏幕并打印出来。但是打印出的值是什么呢?答案是谁都不知道。每次运行程序时结果都可能不同,作者用VisualStudio 2013运行的结果,一次是7177728,下一次5277592。
如果你想亲自运行这个程序有两点需要注意:
确保使用的是release调试模式,(参看6a解决方案配置),否则结果可能是你所用的编译器初始化的结果(VisualStudio使用-858993460初始化)。
如果编译器不允许你运行这个程序并且提示变量未初始化,可以尝试更改为这个程序:
[code]// #include "stdafx.h" // Visual Studio用户无需注释掉这行代码 #include void doNothing(const int &x) { } int main() { int x; // 让编译器误认为x被使用了 doNothing(x); std::cout << x; }
[/code]
使用未初始化的变量是新手常犯的错误之一,不幸的是这也是今后调试程序的挑战之一(因为如果未初始化的变量恰好被分配到一块有合理值比如0的内存区域,程序可能就会正常运行)。
幸运的是,许多现代编译器在编译时检测到一个未初始化的变量时,就会给出相应的警告。例如,在Visual Studio2005中编译上述程序时会给出如下警告:
c:vc2005projectstesttesttest.cpp(11): warning C4700: uninitialized local variable ‘x’ used
一个很好的经验法则是在定义的同时就进行初始化,这会确保你的变量始终有一个一致的值,程序出错时也便于调试。
规则:始终记得初始化你的变量。
小测验
下面的程序会打印出什么值?[code]int x = 5;
x = x - 2;
std::cout << x << std::endl; // #1
int y = x;
std::cout << y << std::endl; // #2
std::cout << x + y << std::endl; // #3
std::cout << x << std::endl; // #4
int z;
std::cout << z << std::endl; // #5
[/code]
答案:点击这里
相关文章推荐
- 18.2.8 1.2定义类+1.3成员变量与成员函数+1.4对象初始化
- C++变量初始化规则
- 【C】为什么静态变量会被初始化为0,而自动变量却不会被初始化?
- oracle 变量声明 初始化 赋值
- C++中一般变量、引用变量、常量、 静态变量、静态常量的初始化问题
- java数组的初始化;数组对象和数组变量
- jspx页面初始化时将View Object中SQL的变量赋bindings中的值 bind variable of the sql in vo
- C#语言学习:变量的声明与初始化的范围(对比C++)
- FTxxxx系列------变量初始化buf失败
- C++变量未进行初始化时的默认值
- Java变量初始化的时机
- Java类的变量初始化顺序
- Java中变量的初始化顺序
- 51平台下初始化文件的引入导致全局变量无法初始化的问题
- 任何时候都应初始化变量
- javascript中未初始化的变量和未定义的变量的区别
- 为什么不能在函数体内部初始化一个由extern关键字标记的变量?
- C# 中关于类初始化时内部变量的执行顺序
- Java中成员变量的初始化顺序浅析
- 基本类型的成员变量(attribute)会被自动初始化,但局部变量(variable)就不会被自动初始化。