收藏 分享(赏)

C++ Const关键字详解.docx

上传人:fmgc7290 文档编号:7219208 上传时间:2019-05-10 格式:DOCX 页数:28 大小:51.55KB
下载 相关 举报
C++ Const关键字详解.docx_第1页
第1页 / 共28页
C++ Const关键字详解.docx_第2页
第2页 / 共28页
C++ Const关键字详解.docx_第3页
第3页 / 共28页
C++ Const关键字详解.docx_第4页
第4页 / 共28页
C++ Const关键字详解.docx_第5页
第5页 / 共28页
点击查看更多>>
资源描述

1、1. const 的用法:看到 const 关键字,C+程序员首先想到的可能是 const 常量。这可不是良好的条件反射。如果只知道用 const 定义常量,那么相当于把火药仅用于制作鞭炮。const 更大的魅力是它可以修饰函数的参数、返回值,甚至函数的定义体。 const 是 constant 的缩写, “恒定不变”的意思。被 const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。所以很多 C+程序设计书籍建议:“Use const whenever you need”。 1. 用 const 修饰函数的参数 如果参数作输出用,不论它是什么数据类型,也不论它采用“指针

2、传递”还是“引用传递” ,都不能加 const 修饰,否则该参数将失去输出功能。 const 只能修饰输入参数: 如果输入参数采用“指针传递” ,那么加 const 修饰可以防止意外地改动该指针,起到保护作用。 例如 StringCopy 函数: void StringCopy(char *strDestination, const char *strSource); 其中 strSource 是输入参数, strDestination 是输出参数。给 strSource 加上 const 修饰后,如果函数体内的语句试图改动 strSource 的内容,编译器将指出错误。 如果输入参数采用“值

3、传递” ,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加 const 修饰。 例如不要将函数 void Func1(int x) 写成 void Func1(const int x)。同理不要将函数 void Func2(A a) 写成 void Func2(const A a)。其中 A 为用户自定义的数据类型。 对于非内部数据类型的参数而言,象 void Func(A a) 这样声明的函数注定效率比较底。因为函数体内将产生 A 类型的临时对象用于复制参数 a,而临时对象的构造、复制、析构过程都将消耗时间。 为了提高效率,可以将函数声明改为 void Func

4、(A 如下语句将出现编译错误:char *str = GetString(); 正确的用法是const char *str = GetString(); 如果函数返回值采用“值传递方式” ,由于函数会把返回值复制到外部临时的存储单元中,加 const 修饰没有任何价值。例如不要把函数 int GetInt(void) 写成 const int GetInt(void)。同理不要把函数 A GetA(void) 写成 const A GetA(void),其中 A 为用户自定义的数据类型。如果返回值不是内部数据类型,将函数 A GetA(void) 改写为 const A / 赋值函数 ; A

5、a, b, c; / a, b, c 为 A 的对象a = b = c; / 正常的链式赋值(a = b) = c; / 不正常的链式赋值,但合法如果将赋值函数的返回值加 const 修饰,那么该返回值的内容不允许被改动。上例中,语句 a = b = c 仍然正确,但是语句 (a = b) = c 则是非法的。 3. const 成员函数任何不会修改数据成员(即函数中的变量 )的函数都应该声明为 const 类型。如果在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非 const 成员函数,编译器将指出错误,这无疑会提高程序的健壮性。以下程序中,类 stack 的成员函数 Ge

6、tCount 仅用于计数,从逻辑上讲 GetCount 应当为 const 函数。编译器将指出 GetCount 函数中的错误。class Stack public:void Push(int elem); int Pop(void); int GetCount(void) const; / const 成员函数private:int m_num; int m_data100; ; int Stack:GetCount(void) const + m_num; / 编译错误,企图修改数据成员 m_numPop(); / 编译错误,企图调用非 const 函数return m_num; cons

7、t 成员函数的声明看起来怪怪的:const 关键字只能放在函数声明的尾部,大概是因为其它地方都已经被占用了。关于 Const 函数的几点规则:a. const 对象只能访问 const 成员函数,而非 const 对象可以访问任意的成员函数 ,包括 const成员函数.b. const 对象的成员是不可修改的,然而 const 对象通过指针维护的对象却是可以修改的.c. const 成员函数不可以修改对象的数据,不管对象是否具有 const 性质.它在编译时,以是否修改成员数据为依据,进行检查.e. 然而加上 mutable 修饰符的数据成员,对于任何情况下通过任何手段都可修改,自然此时的 c

8、onst 成员函数是可以修改它的为什么使用 const?采用符号常量写出的代码更容易维护;指针常常是边读边移动,而不是边写边移动;许多函数参数是只读不写的。const 最常见用途是作为数组的界和 switch 分情况标号(也可以用枚举符代替) 用法 1:常量取 代了 C 中的宏定义,声明时必须进行初始化。const 限制了常量的使用方式,并没有描述常量应该如何分配。如果编译器知道了某 const 的所有使用,它甚至可以不为该 const 分配空间。最简单的常见情况就是常量的值在编译时已知,而且不需要分配存储。C+ Program Language用 const 声明的变量虽然增加了分配空间,但

9、是可以保证类型安全。C 标准中,const 定义的常量是全局的,C+中视声明位置而定。用法 2:指针和常量使用指针时涉及到两个对象:该指针本身和被它所指的对象。将一个指针的声明用 const“预先固定”将使那个对象而不是使这个指针成为常量。要将指针本身而不是被指对象声明为常量,必须使用声明运算符*const。所以出现在 * 之前的 const 是作为基础类型的一部分:char *const cp; /到 char 的 const 指针char const *pc1; /到 const char 的指针const char *pc2; /到 const char 的指针(后两个声明是等同的)从右

10、向左读的记忆方式:cp is a const pointer to char.pc2 is a pointer to const char.用法 3:const 修饰函数传入参数将函数传入参数声明为 const,以指明使用这种参数仅仅是为了效率的原因,而不是想让调用函数能够修改对象的值。同理,将指针参数声明为 const,函数将不修改由这个参数所指的对象。通常修饰指针参数和引用参数:void Fun( const A *in); /修饰指针型传入参数void Fun(const A /修饰引用型传入参数用法 4:修饰函数返回值可以阻止用户修改返回值。返回值也要相应的付给一个常量或常指针。用法

11、5:const 修饰成员函数const 对象只能访问 const 成员函数,而非 const 对象可以访问任意的成员函数,包括 const成员函数;const 对象的成员是不能修改的,而通过指针维护的对象确实可以修改的;const 成员函数不可以修改对象的数据,不管对象是否具有 const 性质。编译时以是否修改成员数据为依据进行检查。Const 深度解析我们也许学习过 const 的使用,但是对于 const 的细致的技术细节却不一定掌握。const 的用法在许多的教材上只是简单的介绍,在这里我们对 const 进行细致的概念以及用法剖析。const 是由 c+采用,并加进标准 c 中,但是

12、他们的意义完全不同,在旧版本(标准前)的 c 中,如果想建立一个常量,必须使用预处理器:#define PI 3.14159此后无论在何处使用 PI,都会被预处理器以 3.14159 替代。编译器不对 PI 进行类型检查,也就是说可以不受限制的建立宏并用它来替代值,如果使用不慎,很可能由预处理引入错误,这些错误往往很难发现。我们也不能得到 PI 的地址(即不能向 PI 传递指针和引用)。c+引入了命名常量的概念,命名常量就像变量一样,只是它的值不能改变,如果试图改变一个const 对象,编译器将会产生错误。 const 和正常变量一样有作用域,所以函数内部的 const也不会影响程序的其余部分

13、。在 c+中 const 可以取代预处理器#define 来进行值替代, const有安全的类型检查,所以不用担心会像预处理器一样引入错误。在通常的情况下 const 同预处理器#define 一样只是将所赋值保存入编译器的符号表中(符号表仅仅在编译时存在,在编译过程中编译器将程序中的名字与之在符号表中定义的数值作简单的替换),在使用的时候进行值替换,并不为 const 创建存储空间。我们将 const 的定义放进头文件里,这样通过包含头文件,可以把 const 定义单独放在一个地方并把它分配给一个编译单元,const 默认为内部连接(内部连接意味着只对正在编译的文件创建存储空间,别的文件可以

14、使用相同的标示符和全局变量,编译器不会发现冲突,外部连接意味着为所有被编译过的文件创建一片单独的存储空间,一般全局变量和函数名的外部连接通过 extern 声明,可以通过其他的文件访问)也就是说 const 仅能被它所定义过的文件访问,在定义一个 const 时,必须赋一个值给它,除非用 extern 做出说明:extern const int a;这表示 const 的定义在其他的什么地方,这里仅仅是一个声明,但是这样的做法使 const 使用了外部连接,也就是说上面的 extern 强制进行了对 const 的存储空间分配,这样我们就无法再用 const 作为常量折叠(在可能的情况下,符号

15、常量的值会代替改名字的出现,这个替代过程叫做常量折叠)使用了,即使我们在其他地方定义了 const 的值,如:extern const int a=3;因为 const 的值被放入了存储单元,在编译的过程中,编译器不会去读存储单元的内容。如果我们这样做:int ba;编译器就会给我们一个错误信息。想不为 const 分配存储空间是不可能的,因为对于复杂的结构,例如集合,编译器不会复杂到将集合保存到它的符号表中,所以必须分配内存空间,这就意味着“这是一块不能改变的存储空间”,当然也就不能在编译期间使用它的值,因为编译器不知道存储的内容:const int i=1,2,3,4;/float fi2

16、; /将得到错误信息,编译器提示不能在数组定义里找到一个常数表达式。因为编译器靠移动栈指针来存储和读取数据。(编译时必须为数组分配内存,但这时数组无法读取 const 常量的值,所以编译器不知道为数组 f 分配多大的空间。)也因此,由于无法避免为 const 分配内存,所以 const 的定义必须默认为内部连接,否则由于众多的 const 在多个文件中分配内存,就会引起错误。下面我们看一段简单有效的代码来说明const 的常量折叠:#include const int a=3;const int b=a+1;float *f=(float*)char cb+3;void main()const

17、 char gc=cin.get();const char c2=gc+3;我们可以看到,a 是一个编译器期间的 const,b 是从 a 中计算出来的,由于 a 是一个 const,b 的计算值来自一个常数表达式,而它自身也是一个编译期间的 const,接着下面指针 f 取得了b 的地址,所以迫使编译器给 b 分配了存储空间,不过即使分配了存储空间,由于编译器已经知道了 b 的值,所以仍然不妨碍在决定数组 c 的大小时使用 b。在主函数 main()里,标识符 gc 的值在编译期间是不知道的,这也意味着需要存储空间,但是初始化要在定义点进行,而且一旦初始化,其值就不能改变,我们发现 c2 是

18、由 gc 计算出来的,它的作用域与其他类型 const 的作用域是一样的,这是对#define 用法的一种改进。在 c+引进常量的时候,标准 c 也引入了 const,但是在 c 中 const 的意思和在 c+中有很大不同,在 c 中 const 的意思是“一个不能改变的普通变量”,const 常量总是被分配存储空间而且它的名字是全局符即 const 使用外部连接。于是在 c 中:const int size=100;char csize;得出一个错误。但是在 c 中可以这样写:const int size;因为 c 中的 const 被默认为外部连接,所以这样做是合理的。在 c 语言中使用

19、限定符 const 不是很有用,如果希望在常数表达式里(必须在编译期间被求值)使用一个已命名的值,必须使用预处理器#define。在 c+中可以使指针成为 const,这很有用,如果以后想在程序代码中改变 const 这种指针的使用,编译器将给出通知,这样大大提高了安全性。在用带有 const 的指针时,我们有两种选择:const 修饰指针指向的对象,或者 const 修饰指针自己指向的存储空间。如果要使指向的对象不发生改变,则需要这样写:const int *p;这里 p 是一个指向 const int 的指针,它不需要初始化,因为 p 可以指向任何标识符,它自己并不是一个 const,但是

20、它所指的值是不能改变的,同样的,我们可以这样写:int const *p;这两种方法是等同的,依据个人习惯以及编码风格不同,程序员自己决定使用哪一种形式。如果希望使指针成为一个 const 必须将 const 标明的部分放在*右边。int a=3;int *const j=也可以是一个 const 指针指向一个 const 对象:const int *j1=int const *j2=这样指针和对象都不能改变,这两种形式同样是等同的。在赋值的的时候需要注意,我们可以将一个非 const 的对象地址赋给一个 const 指针,但是不能将一个 const 对象地址赋给一个非const 指针,因为这

21、样可能通过被赋值的指针改变对象的值,当然也可以用类型的强制转换来进行 const 对象的赋值,但是这样做打破了 const 提供的安全性。const 也被用于限定函数参数和函数的返回值,如果函数参数是按值传递时,即表示变量的初值不会被函数改变,如果函数的返回值为 const 那么对于内部类型来说按值返回的是否是一个cosnt 是无关紧要的,编译器不让它成为一个左值,因为它是一个值而不是一个变量,所以使用 const 是多余的,例如:const int f()return 1;void main()int a=f();但是当处理用户定义类型的时候,按值返回常量就很有意义了,这时候函数的返回值不能

22、被直接赋值也不能被修改。仅仅是非 const 返回值能作为一个左值使用,但是这往往失去意义,因为函数返回值在使用时通常保存为一个临时量,临时量被作为左值使用并修改后,编译器将临时量清除。结果丢失了所有的修改。可以用 const 限定传递或返回一个地址(即一个指针或一个引用):const int * const func(const int *p) static int a=*p;return 参数内的 const 限定指针 p 指向的数据不能被改变,此后 p 的值被赋给静态变量 a,然后将 a 的地址返回,这里 a 是一个静态变量,在函数运行结束后,它的生命期并没有结束,所以可以将它的地址返回

23、。(如果是局部变量,则不可将其值或其地址作为返回值)因为函数返回一个 const int* 型,所以函数 func 的返回值不可以赋给一个非指向 const 的指针 (因为在赋值的的时候需要注意,我们可以将一个非 const 的对象地址赋给一个 const 指针,但是不能将一个 const 对象地址赋给一个非 const 指针,因为这样可能通过被赋值的指针改变对象的值),但它同时接受一个 const int * const 和一个 const int *指针,这是因为在函数返回时产生一个 const 临时指针用以存放 a 的地址,所以自动产生了这种原始变量不能被改变的约定,于是*右边的 con

24、st 只有当作左值使用时才有意义。const 同样运用于类中,但是它的意义又有所不同,我们可以创建 const 的数据成员,const 的成员函数,甚至是 const 的对象,但是保持类的对象为 const 比较复杂,所以 const 对象只能调用 const 成员函数。const 的数据成员在类的每一个对象中分配存储,并且一旦初始化这个值在对象的生命期内是一个常量,因此在类中建立一个 const 数据成员时,初始化工作必须在构造函数初始化列表中。如果我们希望创建一个有编译期间的常量成员,这就需要在该常量成员的前面使用 static 限定符,这样所有的对象都仅有一个实例或者利枚举变量:clas

25、s Xstatic const int size=50;int asize;public:X();const 对象只能调用 const 成员函数,一个普通对象同样可以调用 const 成员函数,因此,const 成员函数更具有一般性,但是成员函数不会默认为 const。声明一个 const 成员函数,需要将 const 限定符放在函数名的后面:void f (void ) const;当我们运用 const 成员函数时,遇到需要改变数据成员,可以用 mutable 进行特别的指定:class Xmutable int i;public:X();void nochange() const;voi

26、d X:nochange const()i+;mutablemutable 可 以 用 来 指 出 ,即 使 结 构 或 者 类 变 量 为 const,其 某 个 成 员 也 可 以 被 修 改在 c+的 类 中 , 如 果 一 个 函 数 被 const 修 饰 , 那 么 它 将 无 法 修 改 其 成 员 变 量 的 ,但 是 如 果 这 个 成 员 变 量 是 被 mutable 修 饰 的 话 , 则 可 以 修 改 。例 如struct datachar name30;mutable int accesses;const data veep = “david“;,0,strcpy

27、(veep.name,“Jimmy“);/ not allowedveep.accesses+; / allowedveep 的 const 限 定 符 禁 止 程 序 修 改 veep 的 成 员 ,但 access 成 员 的 mutable 说明 符 表 示 access 不 受 这 种 限 制const 消除了预处理器的值替代的不良影响,并且提供了良好的类型检查形式和安全性,在可能的地方尽可能的使用 const 对我们的编程有很大的帮助。const 类型定义:指明变量或对象的值是不能被更新,引入目的是为了取代预编译指令 *常量必须被初始化*cons 的作用(1)可以定义 const 常

28、量 例如:const int Max=100;int ArrayMax; (2)便于进行类型检查 例如:void f(const int i) .编译器就会知道 i 是一个常量,不允许修改;(3)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。还是上面的例子,如果在函数体内修改了 i,编译器就会报错;例如: void f(const int i) i=10;/error! (5) 为函数重载提供了一个参考。class Avoid f(int i) file:/一个函数void f(int i) const file:/上一个函数的重载;(6) 可以节省空间,避免不必要的内存分配。例如:

29、#define PI 3.14159 file:/常量宏const doulbe Pi=3.14159; file:/此时并未将 Pi 放入 ROM 中,而是记录在常量表中。 在通常的情况下 const 同预处理器#define 一样只是将所赋值保存入编译器的符号表中(符号表仅仅在编译时存在,在编译过程中编译器将程序中的名字与之在符号表中定义的数值作简单的替换),在使用的时候进行值替换,并不为 const 创建存储空间。double i=Pi; file:/此时为 Pi 分配内存,以后不再分配!double I=PI; file:/编译期间进行宏替换,分配内存double j=Pi; file

30、:/没有内存分配double J=PI; file:/再进行宏替换,又一次分配内存!const 定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define 一样给出的是立即数,所以,const 定义的常量在程序运行过程中只有一份拷贝,而#define 定义的常量在内存中有若干个拷贝。(7) 提高了效率。编译器通常不为普通 const 常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。使用 const(1)修饰一般常量,常数组,常对象修饰符 const 可以用在类型说明符前,也可以用在类型说明符后。 例如:

31、int const x=2; 或 const int x=2;int const a5=1, 2, 3, 4, 5; 或 const int a5=1, 2, 3, 4, 5;class A; const A a; 或 A const a;(2)修饰指针const int *A; 或 int const *A; /const 修饰指向的对象,A 可变,A 指向的对象不可变int *const A; /const 修饰指针 A, A 不可变,A 指向的对象可变 const int *const A; /指针 A 和 A 指向的对象都不可变(3)修饰引用const double 该引用所引用的对象

32、不能被更新(4)修饰函数的返回值:const 修饰符也可以修饰函数的返回值,是返回值不可被改变,格式如下:const int Fun1(); const MyClass Fun2();(5)修饰类的成员函数:const 修饰符也可以修饰类的成员函数,格式如下:class ClassName public:int Fun() const;.;这样,在调用函数 Fun 时就不能修改类里面的数据 (6)在另一连接文件中引用 const 常量extern const int i; /正确的引用extern const int j=10; /错误!常量不可以被再次赋值*放在类内部的常量有什么限制?cla

33、ss Aprivate:const int c3 = 7; / err const 成员只能在定义对象的时候初始化static int c4 = 7; / err,静态数员成员只能在外部初始化static const float c5 = 7; / err;初始化类内部的常量1 初始化列表:class Apublic:A(int i=0):test(i) private:const int i;;2 外部初始化,例如:class Apublic:A() private:static const int i; ;const int A:i=3;C+ const 用法总结#include void

34、 func(const int* p, int n);const char * getStr();class CAprivate:int _nA;public:CA(int a):_nA(a)inline int getA() const/_nA+; /error C2166: l 值指定常数对象return _nA;inline void setA(int a)_nA = a;int main(void)using namespace std;/=/ 1.const 修饰变量使其成为常量/=cout“-const 修饰变量使其成为常量:“endl;const int a = 5;cout“a

35、 = “aendl;/a = 3; /error C2166: l 值指定常数对象/int * pa = /error C2440: “初始化” : 无法从“const int *_w64 ”转换为“int *”/int * const pa = /error C2440: “初始化” : 无法从“const int *_w64 ”转换为“int *const ”const int * pa1 = int const * pa2 = cout“*pa1 = “*pa1endl;cout“*pa2 = “*pa2endl;/*pa1 = 3; /error C2166: l 值指定常数对象/=/

36、 2.const 修饰指针的几种形式/=cout“-const 修饰指针的几种形式:“endl;/第一种,常量指针,指针是常量,不能修改指向int a1 = 3;int a2 = 4;int * const pa = /pa = /error C2166: l 值指定常数对象*pa = 5;cout“a1 = “a1endl;/第二种,指向常量的指针,不能通过此指针修改指向的变量的值int a = 3;const int * pa1 = int const * pa2 = /*pa1 = 5; /error C2166: l 值指定常数对象a = 5;cout“a = “aendl;const

37、 int A = 3;const int *pA = /*pA = 5; /error C2166: l 值指定常数对象/A = 5; /error C2166: l 值指定常数对象/第三种,指向常量的常量指针,既不能修改指向,也不能修改指向变量的值int a1 = 3;int a2 = 4;const int * const pa = /pa = /error C2166: l 值指定常数对象/*pa = 5; /error C2166: l 值指定常数对象/=/ 3.const 修饰函数参数/=cout“-const 修饰函数参数:“endl;/const 一般用于修饰指针或引用类型的函数

38、参数,以避免在函数内部修改其指向的值,/不要用于修饰值传递类型的参数,这样做没有意义。int a = 3;func(/=/ 4.const 修饰函数返回值/=cout“-const 修饰函数返回值:“endl;/返回值为 const 的指针只能赋值给同类型的 const 指针/char * p = getStr(); /error C2440: “初始化” : 无法从“const char *”转换为“char *” 转换丢失限定符const char * p = getStr();coutpendl;/=/ 5.const 修饰类成员函数/=cout“-const 修饰类成员函数:“endl

39、;/在 const 修饰的类成员函数内部,不能修改类成员变量的值CA a(1);couta.getA()endl;cin.get();return 0;void func(const int * p, int n)using namespace std;cout“*p = “*pendl;cout“n = “nendl;/*p = n; /error C2166: l 值指定常数对象const char* getStr()return “hello“;面向对象是 C+的重要特性. 但是 c+在 c 的基础上新增加的几点优化也是很耀眼的就 const 直接可以取代 c 中的#define,以下几

40、点很重要, 学不好后果也也很严重const1. 限定符声明变量只能被读const int i=5;int j=0;.i=j; /非法,导致编译错误j=i; /合法2. 必须初始化const int i=5; /合法const int j; /非法,导致编译错误3. 在另一连接文件中引用 const 常量extern const int i; /合法extern const int j=10; /非法,常量不可以被再次赋值4. 便于进行类型检查用 const 方法可以使编译器对处理内容有更多了解。#define I=10const long /*dapingguo 提醒:由于编译器的优化,使得在

41、 const long i=10; 时 i 不被分配内存,而是已 10 直接代入以后的引用中,以致在以后的代码中没有错误,为达到说教效果,特别地用也会引起后面的编译错误。*/char h=I; /没有错char h=i; /编译警告,可能由于数的截短带来错误赋值。5. 可以避免不必要的内存分配#define STRING “abcdefghijklmnn“const char string=“abcdefghijklmn“;.printf(STRING); /为 STRING 分配了第一次内存printf(string); /为 string 一次分配了内存,以后不再分配.printf(STR

42、ING); /为 STRING 分配了第二次内存printf(string);. 由于 const 定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define 一样给出的是立即数,所以,const 定义的常量在程序运行过程中只有一份拷贝,而 #define 定义的常量在内存中有若干个拷贝。6. 可以通过函数对常量进行初始化int value(); const int i=value();dapingguo 说:假定对 ROM 编写程序时,由于目标代码的不可改写,本语句将会无效,不过可以变通一下:const int 只要令 i 的地址处于 ROM 之外,即可实现:i 通过函数初始

43、化,而其值有不会被修改。7. 是不是 const 的常量值一定不可以被修改呢?观察以下一段代码:const int i=0;int *p=(int*)p=100;通过强制类型转换,将地址赋给变量,再作修改即可以改变 const 常量值。8. 请分清数值常量和指针常量,以下声明颇为玩味:int ii=0;const int i=0; /i 是常量,i 的值不会被修改const int *p1i= /指针 p1i 所指内容是常量,可以不初始化int * const p2i= /指针 p2i 是常量,所指内容可修改const int * const p3i= /指针 p3i 是常量,所指内容也是常量

44、p1i= /合法*p2i=100; /合法 关于 C+中的 const 关键字的用法非常灵活,而使用 const 将大大改善程序的健壮性,参考了康建东兄的 const 使用详解一文,对其中进行了一些补充,写下了本文。1. const 常量,如 const int max = 100; 优点:const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误(边际效应)2. const 修饰类的数据成员。如:class Aconst int size; const 数据成员只在某个对象生存期内是常

45、量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其 const 数据成员的值可以不同。所以不能在类声明中初始化 const 数据成员,因为类的对象未被创建时,编译器不知道 const 数据成员的值是什么。如class Aconst int size = 100; /错误int arraysize; /错误,未知的 sizeconst 数据成员的初始化只能在类的构造函数的初始化表中进行。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现。如class Aenum size1=100, size2 = 200 ;int array1size1;int array2size

46、2; 枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。3. const 修饰指针的情况,见下式:int b = 500; const int* a = / A 为前面自定义的类类型const A a = b; 2) 指针 const 常量初始化的情况:A* d = new A(); const A* c = d; 或者:const A* c = new A(); 3)引用 const 常量初始化的情况: A f; const A / 这样作 e 只能访问声明为 const 的函数,而不能访问一 般的成员函数; 思考 1: 以下的这种赋值方法正确吗? const A* c=new A(); A* e = c; 思考 2: 以下的这种赋值方法正确吗? A* const c = new A(); A* b = c;5. 另外 const 的一些强大的功能在于它在函数声明中的应用。在一个函数声明中,co

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报