第三章 C++数据类型
3.1 文字常量
当一个数值,例如“1”,出现在程序中时,它被称为文字常量:称之为“文字”是因为我们只能以它的值的形式指代它,称之为“常量”是因为它的值不能被改变。文字常量是不可寻址的,尽管它的值也存储在机器内存的某个地方,但是我们没有办法访问它们的地址。
使用未定义行为的程序被称作是不可移植的。虽然程序可能在当前编译器下能正确运行,但是不能保证相同的程序在不同的编译器、或当前编译器的以后版本下编译后,仍能够正确执行。
3.2 变量
变量和文字常量都有存储区,并且有相关的类型。区别在于变量是可寻址的。对于每一个变量,都有两个值与其相关联(数据值,地址值)。
对象声明的作用是使程序知道该对象的类型和名字。它由关键字extern以及跟在后面的对象类型以及对象的名字构成。声明不是定义,不会引起内存分配。实际上,他只是说明了在程序之外的某处有这个变量的定义。
如果一个变量实在全局域内(global scope)定义的,那么系统会保证给它提供初始值0。如果变量是在局部域内(local scope),或是通过new表达式动态分配的,则系统不会向它提供初始值0。这些对象被称为是未初始化的(uninitialized),未初始化的对象不是没有值,而是它的值是未定义的(undefined)。
3.3 指针类型
每个指针都有一个相关的类型。不同数据类型的指针之间的区别在于不是在指针的的表示上,也不在指针所持有的值(地址)上——对所有类型的指针这两方面都是相同的。不同之处在于指针所指的对象的类型上。指针的类型可以指示编译器怎么解释特定地址上内存的内容,以及该内存区域应该跨越多少内存单元。
指针不能被初始化或赋值为其它类型对象的地址值。
例如,已知如下定义:
int *pi = 0;
double dval;
double *pd = &dval;
那么,下列两条语句都会引起编译时刻错误:(无效的类型赋值:int * <== double *)
pi = pd;
pi = &dval;
不是说pi在物理上不能持有与dval相关联内存的地址:它能够。但是不允许,因为虽然说pi和pd都能够持有同样的地址值,但对那块内存的存储布局和内容的解释却完全不同。
3.4 字符串类型
1.C风格字符串:字符串被存储在一个字符数组中,一般通过一个char*类型的指针来操纵它。
2.字符串类型:string类型能够自动将C风格的字符串转换成string对象。例如,这使我们可以将一个C风格的字符串赋给一个string对象:
string s1;
const char *pc = "a character array";
s1 = pc; //ok
但是,反向的转换不能自动执行。对隐式地将string对象转换成C风格的字符串,string类型没有提供支持。例如,下面试图用s1初始化str,就会在编译时失败:
char *str = s1; //编译时刻类型错误。
3.5 const限定修饰符
因为常量在定义后就不能修改,所以它必须被初始化。未初始化的常量定义将导致编译错误:
const double pi; //错误:未初始化的常量
一般编译器不能跟踪指针在程序中任意一点指向的对象。所以非const对象的指针指向一个常量对象,把“试图通过该指针来间接地改变对象值”的动作标记为非法的,这对编译器来说是不可行的。因而任何“试图将一个非const对象的指针指向一个常量对象”的动作都将引起编译错误。但这并不意味着我们不能间接地指向一个const对象,只意味着我们必须声明一个指向常量的指针来做这件事。例如:
const double *cptr;
cptr是一个指向double类型的const指针。(我们可以从右往左把这个定义读为“cptr是一个指向double类型的、被定义成const的对象的指针”。)此中微妙在于cptr本身不是常量。我们可以重新赋值cptr,使其重新指向不同的对象,但不能修改cptr指向的对象。例如:
const double *pc = 0;
const double minWage = 9.60;
//ok:不能通过pc修改minWage
pc = &minWage;
double dval = 3.14;
//ok:不能通过pc修改dval,虽然dval本身不是一个常量
pc = &dval; //ok
dval = 3.14159; //ok
*pc = 3.14159; //错误 (pc指向的对象不能修改。我的问题:pc指向的对象到底是minWage还是dval??)
const对象的地址只能赋值给指向const对象的指针,例如pc。但是,指向const对象的指针可以被赋以一个非const对象的地址,例如:
pc = &dval;
虽然dval不是常量,但试图通过pc修改它的值,仍能会导致编译错误(因为在运行程序的任意一点上,编译器不能确定指针所指的实际对象。)
我们可以定义一个const指针指向一个const或一个非const对象。例如:
int errNumb = 0;
int * const curErr = &errNumb;
curErr是指向一个非const对象的const指针。(我们可以从右到左把定义读为"curErr是一个指向int类型对象的const指针"。)这意味着不能赋给curErr其它的地址值,但可以修改curErr指向的值。
试图给const指针赋值会在编译时刻被标记为错误:
curErr = &myerrNumb; //错误
指向const对象的const指针的定义就是将前面两种定义结合起来。例如:
const double pi = 3.14159;
const double *const pi_ptr = π
在这种情况下,pi_ptr指向的对象的值以及它的地址本身都不能被改变。(我们可以从右往左将定义读作“pi_ptr是指向被定义为const的double类型对象的const指针”。)
3.6 引用类型
引用类型由类型标识符和一个取地址操作符来定义,引用必须被初始化,一旦引用已经定义,它就不能再指向其它的对象(这就是它为什么必须要被初始化的原因)。例如,下列的赋值不会使refVal指向min_val,相反,它会使refVal指向的对象ival的值被设置为min_val的值。
int ival = 1024;
int &refVal = ival;
int min_val = 3;
refVal = min_val;
引用的所有操作实际上都是应用在它所指的对象身上,包括取地址操作符。例如:
refVal += 2;
将refVal指向的对象ival+2.
引用在内部存放的是一个对象的地址,它是该对象的别名。对于不可寻址的值,如文字常量,以及不同类型的对象,编译器为了实现引用,必须生成一个临时对象,引用实际上指向该对象,但用户不能访问它。例如,当我们写:
double dval = 1024;
const int %ri = dval;
编译器将其转换为:
int temp = dval;
const int &ri = temp;
如果我们给ri赋一个新值,则这样做不会改变dval,而是改变temp。对用户来说,就好像修改动作没有生效。
const int ival = 1024;
const int *&pi_ref = &ival; //错误
如果我们从右往左读这个定义,会发现pi_ref是一个引用,它指向定义为const的int型对象的一个指针。我们的引用不是指向一个常量,而是指向一个非常量指针,指针又指向一个const对象。正确的定义如下:
const int ival = 1024;
const int *const &pi_ref = &ival; //ok
指针和引用主要有两个区别:引用必须总是指向一个对象。如果一个引用给另外一个引用赋值,那么改变的是被引用的对象而不是引用本身。
假定有以下代码:
int &ri1 = ival1, &ri2 = ival2;
档我们写出这样的赋值语句时:
ri1 = ri2;
改变的是ival1,而不是引用本身。赋值之后,两个引用仍能指向原来的对象。
3.9 数组类型
数组定义由类型名、标识符和维数组成。维数值必须是常量表达式——即必须在编译时刻计算出它的值。这意味着非const的变量不能被用来指定数组的维数,对于非const的对象,系统只能在运行时刻访问它的值。
用户必须清楚,C++没有提供编译时刻或运行时刻对数组下标的范围检查。除了程序员自己注意细节,并彻底测试自己的程序外,没有别的办法可以防止数组越界。
3.10 vector容器类型
当我们用一个给定的大小定义一个vector时,例如:
vector<int> ia(10);
任何一个插入操作(push_back())都将增加vector的大小,而不是覆盖某个现有的元素。
3.15 类类型
类的成员函数可以被定义在类的定义中,也可以定义在外面。在类定义之外定义的成员函数不但要告诉编译器它们的名字、返回类型、参数表,而且要说明它们所属的类。我们应当把成员函数的定义放到一个程序文本文件中中(例如,String.C),并且把含有该类定义的头文件(如String.h)包含进来。
如果有某个要频繁调用的小函数,把它声明成内联inline函数是个好办法。在类定义内部定义的成员函数,再缺省情况下被设置为inline。在类外面定义的成员函数必须显示地声明为inline。
假定一个函数不是类的成员函数,没有权限访问类的私有成员变量,有两种可能的解决方案:一种是给函数赋予一个特殊的访问许可【把它声明为类的友元friend】,第二种方法是提供一个内联的访问函数。
版权声明:
作者:王老头
出处:http://www.cnblogs.com/wmr95/articles/7282133.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,并在文章页面明显位置给出原文链接,否则,作者将保留追究法律责任的权利。
浙公网安备 33010602011771号