变量提供一个具有名的、可供程序操作的存储空间。C++中的每个变量都有其数据类型,数据类型决定着变量所占的空间大小和布局方式、该空间能存储的值的范围,以及变量能参与的运算。对于C++程序员来说,“变量”和“对象”一般可以互换使用。
1.变量的定义
变量定义的基本形式是:首先是类型说明符,随后紧跟一个或多个变量名组成的列表,其中变量名以逗号分开,最后以分好结束。列表中的每个变量名的类型都由类型说明符决定,定义时还可以为一个或多个变量赋初值。
int a=0,b,c=a;
std::string s("1234");
初始值
初始化不是赋值,初始化的含义是创建变量时赋予其一个初始化值,而赋值的含义是把对象的当前值擦出,而以一个新值来替代。
列表初始化
C++定义了初始化的好几种不同形式,这也是初始化问题复杂的一个体现。比如,想定义一个int型变量i并且初始化为0,可以有下面四种方法:
int i = 0;
int i = {0};
int i(0);
int i{0};
C++11新标准,花括号初始化变量得到全面应用,这种初始化形式有一个重要特点:如果使用列表初始化且初始化值存在丢失信息的风险,则编译器将报错:
long double ld = 3.1415926;
int a{ld}, b = {ld}; //错误,转换未执行,存在丢失信息的风险
int c(ld), d = ld; //正确,转换执行,且确实丢失了部分值
默认初始化
一个变量定义时如果没有指定初始值,则变量被默认初始化。
定义于函数体之外的变量,如果没有指定初始值,则初始化为0。定义于函数体内的变量,如果没有初始化,则不被初始化,初始化值是未定义的,如果试图拷贝或者访问改变量,将引发错误。建议初始化每个内置类型变量,虽然并非必须这么做,但是如果我们不能确保初始化后程序
安全,那么这么做不失为一种简单可靠的方法。
2.变量声明和定义的关系
为了允许程序拆分成多个逻辑部分来编写,C++语言允许分离式编译机制。改机制允许将程序分割为若干个文件,每个文件可被独立编译。
为了支持分离式编译,C++将声明和定义区分开来。声明使得名字为程序所致,一个名字如果想使用别处定义的名字则必须包含对那个名字的声明。而定义负责创建与名字关联的实体。
如果想声明一个变量而非定义它,就在变量名前添加关键字extern.,而且不要显示得初始化变量值。
变量只能被定义一次,但是可以声明多次。
extern int i; //声明i而非定义
int j; //声明j并且定义
extern k=0; //定义k而非声明
3.标识符
C++的标识符字母、数字和下划线组成,其中必须以字母和下划线开头,标识符的长度没有限制,但对大小写敏感。标识符不能出现连续的两个下划线,也不能以下划线紧连大写字母开头。此外,定义在函数体外的标识符不能以下划线开头。
C++保留了部分名字供语言本身使用,这些名字不能被用作标识符。
变量命名规范
标识符要能体现实际含义
变量名一般用小写字母表示,如index,不要使用Index或者INDEX
用户自定义的类一般以大写字母开头
如果标识符由多个单词组成,则单词之间要用明显表示,比如SettingView或者setting_view,不要写成settingview
4.名字的作用域
作用域是程序的一部分,在其中名字有其特定含义,C++语言中大多数作用域都以花括号分隔。
同一个名字在不同的作用域中可能指向不同的实体,名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束。
一般来说,在对象第一次被使用的地方附近定义它是一种好的选择,因为这样做更有助于找到变量的定义。更重要的是,当变量的定义于它第一次使用的地方很近时,我们也会赋予它一个比较合理的初始值。
嵌套作用域
作用域能彼此包含,被包含的作用域成为内层作用域,包含着别的作用域的作用域成为外层作用域。作用域中一旦声明了一个名字,它所嵌套的所有作用域都能访问该名字。
如果函数有可能用到某个全局变量,则不宜再定义一个同名的局部变量。