ImageVerifierCode 换一换
格式:DOCX , 页数:8 ,大小:21.12KB ,
资源ID:16699766      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/16699766.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(C语言const的用法Word下载.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

C语言const的用法Word下载.docx

1、class A.void f(int i) . file:/一个函数 void f(int i) const . file:/上一个函数的重载;(6) 可以节省空间,避免不必要的内存分配。#define PI 3.14159 file:/常量宏const doulbe Pi=3.14159; file:/此时并未将Pi放入ROM中double i=Pi/此时为Pi分配内存,以后不再分配!double I=PI/编译期间进行宏替换,分配内存double j=/没有内存分配double J=/再进行宏替换,又一次分配内存!const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#de

2、fine一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。(7) 提高了效率。编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。3、如何使用const?(1)修饰一般常量 一般常量是指简单类型的常量。这种常量在定义时,修饰符const可以用在类型说明符前,也可以用在类型说明符后。int const x=2或const int x=(2)修饰常数组 定义或说明一个常数组可采用如下格式: int const a5=1, 2,

3、3, 4, 5;const int a5=1, 2, 3, 4, 5;(3)修饰常对象常对象是指对象常量,定义格式如下:class A; const A a;A const a; 定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符const可以放在类名后面,也可以放在类名前面。(4)修饰常指针const int *A;/const修饰指向的对象,A可变,A指向的对象不可变 int const *A; file:/const修饰指向的对象,A可变,A指向的对象不可变int *const A;/const修饰指针A, A不可变,A指向的对象可变 const int *const A;/

4、指针A和A指向的对象都不可变 (5)修饰常引用使用const修饰符也可以说明引用,被说明的引用为常引用,该引用所引用的对象不能被更新。其定义格式如下: const double & v; (6)修饰函数的常参数const修饰符也可以修饰函数的传递参数,格式如下:void Fun(const int Var);告诉编译器Var在函数体中的无法改变,从而防止了使用者的一些无意的或错误的修改。(7)修饰函数的返回值:const修饰符也可以修饰函数的返回值,是返回值不可被改变,格式如下:const int Fun1();const MyClass Fun2();(8)修饰类的成员函数:const修饰符

5、也可以修饰类的成员函数,格式如下:class ClassName public: int Fun() const; .;这样,在调用函数Fun时就不能修改类里面的数据 (9)在另一连接文件中引用const常量extern const int i;/正确的引用extern const int j=/错误!常量不可以被再次赋值另外,还要注意,常量必须初始化!const int i=54、几点值得讨论的地方:(1)const究竟意味着什么?说了这么多,你认为const意味着什么?一种修饰符?接口抽象?一种新类型?也许都是,在Stroustup最初引入这个关键字时,只是为对象放入ROM做出了一种可能,

6、对于const对象,C+既允许对其进行静态初始化,也允许对他进行动态初始化。理想的const对象应该在其构造函数完成之前都是可写的,在析够函数执行开始后也都是可写的,换句话说,const对象具有从构造函数完成到析够函数执行之前的不变性,如果违反了这条规则,结果都是未定义的!虽然我们把const放入ROM中,但这并不能够保证const的任何形式的堕落,我们后面会给出具体的办法。无论const对象被放入ROM中,还是通过存储保护机制加以保护,都只能保证,对于用户而言这个对象没有改变。换句话说,废料收集器(我们以后会详细讨论,这就一笔带过)或数据库系统对一个const的修改怎没有任何问题。(2)位元

7、const V.S. 抽象const?对于关键字const的解释有好几种方式,最常见的就是位元const 和 抽象const。下面我们看一个例子:A f(const A& a);如果采用抽象const进行解释,那就是f函数不会去改变所引用对象的抽象值,如果采用位元const进行解释,那就成了f函数不会去改变所引用对象的任何位元。我们可以看到位元解释正是c+对const问题的定义,const成员函数不被允许修改它所在对象的任何一个数据成员。为什么这样呢?因为使用位元const有2个好处:最大的好处是可以很容易地检测到违反位元const规定的事件:编译器只用去寻找有没有对数据成员的赋值就可以了。另

8、外,如果我们采用了位元const,那么,对于一些比较简单的const对象,我们就可以把它安全的放入ROM中,对于一些程序而言,这无疑是一个很重要的优化方式。(关于优化处理,我们到时候专门进行讨论) 当然,位元const也有缺点,要不然,抽象const也就没有产生的必要了。首先,位元const的抽象性比抽象const的级别更低!实际上,大家都知道,一个库接口的抽象性级别越低,使用这个库就越困难。其次,使用位元const的库接口会暴露库的一些实现细节,而这往往会带来一些负面效应。所以,在库接口和程序实现细节上,我们都应该采用抽象const。有时,我们可能希望对const做出一些其它的解释,那么,就

9、要注意了,目前,大多数对const的解释都是类型不安全的,这里我们就不举例子了,你可以自己考虑一下,总之,我们尽量避免对const的重新解释。(3)放在类内部的常量有什么限制?看看下面这个例子:private:const int c3 = 7; / ?static int c4 = 7;static const float c5 = 7;你认为上面的3句对吗?呵呵,都不对!使用这种类内部的初始化语法的时候,常量必须是被一个常量表达式初始化的整型或枚举类型,而且必须是static和const形式。这显然是一个很严重的限制!那么,我们的标准委员会为什么做这样的规定呢?一般来说,类在一个头文件中被声

10、明,而头文件被包含到许多互相调用的单元去。但是,为了避免复杂的编译器规则,C+要求每一个对象只有一个单独的定义。如果C+允许在类内部定义一个和对象一样占据内存的实体的话,这种规则就被破坏了。(4)如何初始化类内部的常量?一种方法就是static 和 const 并用,在内部初始化,如上面的例子;另一个很常见的方法就是初始化列表:A(int i=0):test(i) const int i;还有一种方式就是在外部初始化,例如:A() static const int i;/注意必须是静态的!const int A:i=3;(5)常量与数组的组合有什么特殊吗?我们给出下面的代码:const int

11、 size3=10,20,50;int arraysize2有什么问题吗?对了,编译通不过!为什么呢?const可以用于集合,但编译器不能把一个集合存放在它的符号表里,所以必须分配内存。在这种情况下,const意味着不能改变的一块存储。然而,其值在编译时不能被使用,因为编译器在编译时不需要知道存储的内容。自然,作为数组的大小就不行了:) 你再看看下面的例子:test2(1,2) file:/你认为行吗?const int test2;vc6下编译通不过,为什么呢?关于这个问题,前些时间,njboy问我是怎么回事?我反问他:你认为呢?他想了想,给出了一下解释,大家可以看看:我们知道编译器堆初始化

12、列表的操作是在构造函数之内,显式调用可用代码之前,初始化的次序依据数据声明的次序。初始化时机应该没有什么问题,那么就只有是编译器对数组做了什么手脚!其实做什么手脚,我也不知道,我只好对他进行猜测:编译器搜索到test发现是一个非静态的数组,于是,为他分配内存空间,这里需要注意了,它应该是一下分配完,并非先分配test0,然后利用初始化列表初始化,再分配test1,这就导致数组的初始化实际上是赋值!然而,常量不允许赋值,所以无法通过。呵呵,看了这一段冠冕堂皇的话,真让我笑死了!njboy别怪我揭你短呀:)我对此的解释是这样的:C+标准有一个规定,不允许无序对象在类内部初始化,数组显然是一个无序的

13、,所以这样的初始化是错误的!对于他,只能在类的外部进行初始化,如果想让它通过,只需要声明为静态的,然后初始化。这里我们看到,常量与数组的组合没有什么特殊!一切都是数组惹的祸!(6)this指针是不是const类型的?this指针是一个很重要的概念,那该如何理解她呢?也许这个话题太大了,那我们缩小一些:this指针是个什么类型的?这要看具体情况:如果在非const成员函数中,this指针只是一个类类型的;如果在const成员函数中,this指针是一个const类类型的;如果在volatile成员函数中,this指针就是一个volatile类类型的。(7)const到底是不是一个重载的参考对象?先

14、看一下下面的例子:/一个函数上面是重载是没有问题的了,那么下面的呢?void f(const int i) . file:/?/这个是错误的,编译通不过。那么是不是说明内部参数的const不予重载呢?再看下面的例子:void f(int& ) . file:void f(const int&这个程序是正确的,看来上面的结论是错误的。为什么会这样呢?这要涉及到接口的透明度问题。按值传递时,对用户而言,这是透明的,用户不知道函数对形参做了什么手脚,在这种情况下进行重载是没有意义的,所以规定不能重载!当指针或引用被引入时,用户就会对函数的操作有了一定的了解,不再是透明的了,这时重载是有意义的,所以规

15、定可以重载。(8)什么情况下为const分配内存?以下是我想到的可能情况,当然,有的编译器进行了优化,可能不分配内存。A、作为非静态的类成员时;B、用于集合时;C、被取地址时;D、在main函数体内部通过函数来获得值时;E、const的 class或struct有用户定义的构造函数、析构函数或基类时;F、当const的长度比计算机字长还长时;G、参数中的const;H、使用了extern时。不知道还有没有其他情况,欢迎高手指点:(9)临时变量到底是不是常量?很多情况下,编译器必须建立临时对象。像其他任何对象一样,它们需要存储空间而且必须被构造和删除。区别是我们从来看不到编译器负责决定它们的去留

16、以及它们存在的细节。对于C+标准草案而言:临时对象自动地成为常量。因为我们通常接触不到临时对象,不能使用与之相关的信息,所以告诉临时对象做一些改变有可能会出错。当然,这与编译器有关,例如:vc6、vc7都对此作了扩展,所以,用临时对象做左值,编译器并没有报错。(10)与static搭配会不会有问题?假设有一个类:static void f() const .我们发现编译器会报错,因为在这种情况下static不能够与const共存!因为static没有this指针,但是const修饰this指针,所以.(11)如何修改常量?有时候我们却不得不对类内的数据进行修改,但是我们的接口却被声明了cons

17、t,那该怎么处理呢?我对这个问题的看法如下:1)标准用法:mutabletest(i) void Setvalue(int i)const test=imutable int test;/这里处理!2)强制转换:const_castvoid Setvalue(int i)const const_cast (test)=i; /这里处理!int test;3)灵活的指针:int* *test=i;int* test;4)未定义的处理test(i) int *p=(int*)&test; *p=i;注意,这里虽然说可以这样修改,但结果是未定义的,避免使用!5)内部处理:this指针void Set

18、value(int i)const (A*)this)-test=i;6)最另类的处理:空间布局test(i),c(a) char c;const int test;int main()A a(3);A* pa=&a;char* p=(char*)pa;int* pi=(int*)(p+4);/利用边缘调整*pi=5;/此处改变了test的值!return 0;虽然我给出了6中方法,但是我只是想说明如何更改,但出了第一种用法之外,另外5种用法,我们并不提倡,不要因为我这么写了,你就这么用,否则,我真是要误人子弟了:(12)最后我们来讨论一下常量对象的动态创建。既然编译器可以动态初始化常量,就自然可以动态创建,例如:const int* pi=new const int(10);这里要注意2点:1)const对象必须被初始化!所以(10)是不能够少的。2)new返回的指针必须是const类型的。那么我们可不可以动态创建一个数组呢?答案是否定的,因为new内置类型的数组,不能被初始化。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1