变量、对象

变量提供一个具名的,可供程序操作的存储空间。C++中每个变量都有其数据类型,数据类型决定着变量所占内存空间的大小和布局方式、该空间能存储的值的范围,以及变量能参与的运算。对C++来说,变量(variable)和对象(object)一般可以互换使用。


对象

  C++在很多场合都会使用对象(object)这个名词。通常情况下,对象是指一块能存储数据并具有某种类型的内存空间。
   一些人仅在与类有关的场景下才使用“对象”这个词。另一些人则把命名的对象和未命名的对象区分开来,把命名了的对象叫做变量。还有一些人把对象和值区分开来,其中对象指能被程序修改的数据,而值(value)指只读的数据。
  本书遵循大多数人的习惯用法,即认为对象是具有某种数据类型的内存空间。在使用对象这个词时,并不严格区分是类还是内置类型,也不区分是否命名或是否可读。


初始值

当对象在创建时获得了一个特定的值,我们说这个对象被初始化(initialized)了。
  在C++中,初始化和赋值是两个完全不同的操作。初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来替代。

列表初始化

作为C++11的新标准,用花括号来初始化的形式被称为列表初始化(list initialization)。现在,无论是初始化对象还是某些时候为对象赋新值,都可以使用这样一组由花括号括起来的初始值了。
  如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将报错:

long double ld = 3.14159;
int a{ld};				// 错误:转换未执行,因为存在丢失信息的危险
int b(ld);				// 正确:转换执行,且确实丢失了部分值

其中,至少ld的小数部分会丢失掉,而且int也可能存不下ld的整数部分。

默认初始化

默认值到底是什么由变量类型决定,同时定义变量的位置也会对此有影响。
  如果是内置类型的变量未被显式初始化,它的值由定义的位置决定。定义于任何函数体之外的变量被初始化为0,定义在函数体内部的内置类型变量将不被初始化(uninitiated)。一个未被初始化的内置类型变量的值时未定义的。
  每个类各自决定其初始化对象的方式。而且,是否允许不经初始化就定义对象也由类自己决定。如果类允许这种行为,它将决定对象的初始值到底是什么。

定义于函数体内的内置类型的对象如果没有初始化,则其值为定义。
类的对象如果没有显示的初始化,则其值由类确定。

变量声明和定义的关系

  为了允许把程序拆分成多个逻辑部分来编写,C++语言支持分离式编程(separate compilation)机制,该机制允许把程序分割为若干个文件,每个文件可被独立编译。
  如果将程序分为多个文件,则需要有在文件间共享代码的方法。为了支持分离式编译,C++语言将声明和定义区分开来。声明(declaration)使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。而定义(definition)负责创建与名字关联的实体。
  变量声明规定了变量的类型和名字,在这一点上定义与之相同。但是除此之外,定义还申请存储空间,也可能会为变量赋一个初始值。
  如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显式地初始化变量。

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

任何包含了显式初始化地声明即成为定义。extern语句如果包含初始值就不再是声明,而变成定义了。

extern double pi = 3.14;		// 定义

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

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

名字的作用域

  不论是在程序的什么位置,使用到的每个名字都会指向一个特殊的实体:变量、函数、类型等。然而,同一个名字如果出现在程序的不同位置,也可能指向的是不同实体。
  作用域(scope)是程序的一部分,在其中名字有其特定的含义。C++语言中大多数作用域都以花括号分割。同一个名字在不同的作用域中可能指向不同的实体。名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束。
  名字main定义于所有花括号之外,它和其他大多数定义在函数体之外的名字一样拥有全局作用域(global scope)。在main函数中定义的变量拥有块作用域(block scope)。
  作用域能彼此包含,被包含(或则说被嵌套)的作用域称为内层作用域(inner scope),包含着别的作用域的作用域称为外层作用域(outer scope)。作用域中一旦声明了某个名字,它所嵌套着的所有作用域中都能访问该名字。同时,允许在内层作用域中重新定义外层作用域已有的名字。
  正在作用域内:in scope

// 显示地访问全局变量rescued
cout << ::rescued <<endl;

使用作用域操作符来覆盖默认的作用域规则,因为全局作用域本身并没有名字,所以当作用域操作符的左侧为空时,向全局作用域发出请求获取作用域操作符右侧名字对应的变量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值