C++Primer第2章(2)变量

2.2 变量

​ 变量提供一个具名的,可供程序操作的存储空间.C++中的每个变量都有其数据类型,数据类型决定着变量所占内存空间的大小和布局方式,该控件能存储的值的范围,以及变量能参与的运算.

2.2.1 变量定义

​ 变量定义的基本形式是:首先是类型说明符(type specifier ),随后紧跟由一个或多个变量名组成的列表,其中变量名以逗号分隔,最后以分号结束.定义时可以为一个或多个变量赋初值.

int sum = 0, value, units_sold = 0;

image-20211125144800980

初始值

​ 当对象在创建时获得了一个特定的值,我们说这个对象被初始化了.用于初始化变量的值可以是任意复杂的表达式.

// 正确:price先被定义并赋值,随后被用于初始化discount
double price = 109.99, discount = price * 0.16;
// 正确:调用函数applyDiscount,然后用函数的返回值初始化salePrice
double salePrice = applyDicount(price, discount);

初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义时把对象的当前值擦除,而以一个新值来代替.

列表初始化

​ C++定义了初始化的多种形式.

 	int units_sold = 0;
    int units_sold = {0};
    int units_sold{0};
    int units_sold(0);

用花括号来初始化变量的形式被称为列表初始化.

​ 当用于内置类型的变量时,如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将报错.

image-20211125175532719

默认初始化

​ 如果定义变量时没有指定初值,则变量被默认初始化(default initialized).默认值到底是什么有变量类型决定,同时定义变量的位置也会对此有影响.

​ 定义于任何函数体之外的变量被初始化为0.定义在函数体内部的内置类型变量将不被初始化(uninitialized).

定义与函数体内的内置类型的对象如果没有初始化,则其值未定义.类的对象如果没有显式地初始化,则其值由类确定.

image-20211125185822111

2.2.2 变量声明和定义的关系

​ 为了允许把程序拆分成多个逻辑部分来编写,C++支持**分离式编译(separate compilation)**机制,该机制允许将程序分割成为若干个文件,每个文件可被独立编译.

​ 为了支持分离式编译,C++将声明和定义区分开来.**声明(declaration)使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明.而定义(definition)**负责创建与名字关联的实体.

变量声明规定了变量地类型和名字,定义还申请存储空间,也可能会为变量赋一个初始值.

​ 如果想声明一个变量而非定义它,可以在变量名前加关键字extern.

extern int i;	//声明i而非定义i
int j;			//声明并定义j

​ 我们能给由extern关键字标记的变量赋一个初始值,但这么做也就抵消了extern地作用.extern语句如果包含初始值就不再是声明了,而变成定义了.

extern double pi = 3.1415;   //定义

​ 在函数体内部,如果试图初始化一个由extern关键字标记的变量,将引发错误.

image-20211125191003678

变量能且只能被定义一次,但可以被多次声明

image-20211125191056455

2.2.3 标识符

C++地标识符(identifier)由字母,数字和下划线组成,必须以字母或下划线开头.标识符的长度没有限制,但是对大小写字母敏感.

变量命名规范

  • 标识符要能体现实际含义
  • 变量名一般用小写字母,如index,不要使用Index或INDEX
  • 用户自定义的类名一般以大写字母开头,如Sales_item.
  • 如果标识符由多个单词组成,则单词间应有明显区分,如student_loan或studentLoan,不要使用studentloan.

C++关键字和操作符替代名不能用作标识符.

image-20211125191517488

2.2.4 名字的作用域

作用域是程序的一部分,在其中名字有其特定的含义.C++中大多数作用域都以花括号分隔.

​ 同一个名字在不同地作用域中可能指向不同的实体.名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束.

#include<iostream>
using namespace std;
int main()
{
	int sum = 0;
	// sum 用于存放从1到10所有数的和
	for(int val = 1; val <= 10; ++val){
		sum += val;  // 等价于sum = sum + val;
	}
	cout<<"Sum of 1 to 10 inclusive is "<< sum <<endl;
	return 0;
}

​ 名字main定义于所有花括号之外,它和其他大多数定义在函数体之外的名字一样拥有全局作用域(global scope).一旦声明后,全局作用域内的名字在整个程序的范围内都可以使用.名字sum定义于main函数所限定的作用域内,从声明sum开始到main函数结束为止都可以访问它,但是除了main函数所在的块就无法访问了,因此说变量sum拥有块作用域(block scope).名字val定义于for语句内,在for语句之内可以访问val,但是在main函数的其他部分就不能访问它了.

image-20211125192443958

嵌套的作用域

​ 作用域能彼此包含,被包含(被嵌套)的作用域称为内层作用域(inner scope),包含着别的作用域的作用域称为外层作用域(outer scope).

​ 作用域中一旦声明了某个名字,它所嵌套着的所有该作用域中都能访问该名字.同时,允许在内层作用域重新定义外层作用域已有的名字.

image-20211125193217500

​ 输出#1出现在局部变量reused定义之前,因此这条语句使用全局作用域中定义的名字reused,输出420。输出#2发生在局部变量reused定义之后,此时局部变量reused正在作用域内(in scope),因此第二条输出语句使用的是局部变量reused而非全局变量,输出0 0。输出#3使用作用域操作符来覆盖默认的作用域规则,因为全局作用域本身并没有名字,所以当作用域操作符的左侧为空时,向全局作用域发出请求获取作用域操作符右侧名字对应的变量。结果是,第三条输出语句使用全局变量reused,输出42 0。

sed而非全局变量,输出0 0。输出#3使用作用域操作符来覆盖默认的作用域规则,因为全局作用域本身并没有名字,所以当作用域操作符的左侧为空时,向全局作用域发出请求获取作用域操作符右侧名字对应的变量。结果是,第三条输出语句使用全局变量reused,输出42 0。

如果函数有可能用到某全局变量,则不宜再定义一个同名的局部变量.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

远离蒙昧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值