第七篇 更多的数据类型和运算符
本章我们又回到数据类型和运算符的话题上。除了目前我们使用过的那些数据类型之外,C++还支持几种别的数据类型,其中就包括对我们已经学过的数据类型的修饰符,还有包括枚举和类型定义的别的数据类型。C++中还提供了几种附加的运算符,这些运算符极大地扩展了编程任务的范围。这其中就包括位运算符,移位运算符号和sizeof运算符。
必备技能7.1:const和volatile 修饰字
C++中有两种可以影响变量访问或者修修改方式的限定字。它们就是const和volatile。通常,它们被称为CV限定字。
const
被const修饰的变量在程序执行期间其值是不能被修改的。因此,一个被const修饰的“变量”实际上并不是真正意义上的变量。但是我们还是可以给一个被const修饰的变量进行初始化的。例如:
const int max_users = 9;
就创建了一个名称为max_users的变量,其值为9。它可以像其他变量一样应用于任何的表达式。但是程序不能修改其值。
const最常用的就是被用来创建一个有名称的常量。通常,程序中出于不同的目的需要使用同一个值。例如,程序中可以还有多个大小一样的数组。在这种情况下,我们就可以使用一个被const修饰的变量来指明数组的大小。这种方式的优点就是如果以后需要修改数组的大小,我们只需要修改这个被const修饰的变量的值,然后对程序进行重新编译即可。而不需要在每个数组声明的地方都对其大小进行修改,并且这很容易引入错误。下面的程序演示了const的用法。
- #include <iostream>
- using namespace std;
- //创建一个常量,名称为num_employees,其值为
- const int num_employees = 100;
- int main()
- {
- int empNums[num_employees];
- double salary[num_employees];
- char *names[num_employees];
- //...
- return 0;
- }
在上面的程序中,如果我们需要为数组指定新的大小,我们是需要修改声明变量num_employees的初始化值,然后重新编译即可。三个数组的大小就都会自动地变为新的值。
const的另外一个重要的用法就是防止通过指针来修改对象。例如,有时候我们需要避免在一个函数中对指针参数指向的对象进行修改。为了达到这个目的,我们只需要把指针参数声明为cont就可以了。这样就可以防止在函数中通过指针修改对象了。也即是说,如果指针参数前面用const进行修饰了,那么函数中的语句就不能通过该指针修改对象了。例如下面程序中的函数negate()返回的是其指针参数指向对象的相反数。这里就用到了const修饰指针参数,从而避免了在函数中通过指针修改对象的值。
- //使用常量指针参数
- #include <iostream>
- using namespace std;
- int negate(const int *val);
- int main()
- {
- int result;
- int v = 10;
- result = negate(&v);
- cout << v << " negated is " << result;
- cout << "\n";
- return 0;
- }
- int negate(const int *val)
- {
- return -*val;
- }
- //This won’t work!
- int negate(const int *val)
- {
- *val = -*val;
- return *val;
- }
const修饰符同样可以作用于引用参数,来防止函数修改引用参数的值。例如,下面版本中的negate()函数是错误的,因为它企图修改val引用的变量的值。
- //This won’t work!
- int negate(const int &val)
- {
- val = -val; //错误,val引用对象不能被修改
- return val;
- }
修饰字volatile告诉编译器,被其修饰的变量可能会被程序中没有明确指定的方式被修改。例如,在定时中断处理程序中,我们可以传入一个全局变量的地址,每次定时中断后,处理程序就会更新该全局变量的值。在这种情况下,该全局变量的值就会在我们程序没有明确赋值的情况下被修改。变量被外部修改之所以对C++来说是特别重要的,是因为C++编译器经常会基于“如果变量没有出现在赋值运算符的左侧,则变量的值就没有改变”这种假设来对表达式进行优化。然而,如果超出了程序范围之外的因素如果导致变量的值被修改,则这种优化就会导致问题。为了避免这种问题的出现,我们必须在声明变量的时候使用volatile修饰字。如下:
volatile int current_users;
由于变量被volatile所修饰,每次我们在引用current_users的时候,它的值都会被重新获取。
练习:
1. 被const修饰的变量的值是否在程序中可以被修改?
2. 如果一个变量的值会被程序之外的事件处理所修改,我们应该如何声明这个变量?
存储类型说明字
C++中有5种存储类型说明字,它们是:
auto
extern
register
static
mutable
这些说明字告诉编译器如何存储变量。存储类型说名字是放置在变量声明的最前面的。其中的mutable说名字只能用于类对象,关于这点我们将在本书的后面进行介绍。
本章中,我们只对其它的说名字进行介绍。
auto
auto说明字用于声明一个局部变量。然而,它很少被用到。这是因为局部变量缺省地就是auto的。在程序中我们基本上看不到这个说明字。这个说明字是从C语言中继承而来的。