C++中const、static、 static const和const static的初始化以及(3)

2019-08-30 11:35

因为n是不能被修改的,那这样还不如直接写int str[10];从而省去了声明、定义n的事。 或许我举的例子不够恰当,没能体现出那位高人的本意。

还有一点在下想说,那就是关于static const int的事,本人纠结了很久了,包括为什么在类内可以直接初始化它,怎么用,有什么好处,编译器到底为不为它分配内存,什么情况下进行常量折叠,等等等等。我查阅了很多资料(包括国外的编程网站),也请教了很厉害的老师 ,但最终也没能完全弄清楚。一来是在下水平低,二来是各种说法让我莫衷一是,有的说法我可以自己编程验证,但有的暂时还不知道好如何验证。现在只搞清楚了(算是清楚了吧)一点儿,那就是从汇编来看,static const int a=1;这句无论写在哪里,都不会分配空间,但写在函数中(无论什么函数),并把return a时,将会对a分配内存,当然,在任何地方对a取地址或引用a时,也将对a分配空间。(读者可以参考我前边提到的《const的思考》,里面比较详尽地给出了什么时候给const数据分配内存,我想static const也是如此)当直接使用a时,例如int d;d=a;或cout << Myclass::f;(f为类Myclass下的public的static const int),都不分配空间。还有,有人说static const int n=30;与#define n 30作用类似,但前者优于后者,原因是前者在使用时只分配一次内存,后者每次使用时都分配内存,但在下经过试验貌似不是这样,两者在直接使用时都不分配内存,通过函数return时,都将分配内存。(以上关于内存分配的讨论很可能有错,因为本人对汇编并不太懂)本人感觉前者的优点主要是可以封装在类中,实现了C++的封装性。 这就是在下所知道的。所以,在下在这里虔诚呼吁,凡是对以上问题明白的,哪怕是略知一二,也万望您不吝赐教。

好了,至此,关于初始化的问题就说到这里,其中也扯进来一些相关问题,可能让读者感到烦乱,而在下这样做的目的主要是把在下知道的都与大家分享,希望让像我一样的初学者能更明白地,较为全面地学到一些东西;同时多多暴露自己的问题和错误,以期在大家的批评指正下提高。由此给您造成的阅读不便,敬请谅解。

下面,在简单说一下const、 static 、static const的值的修改问题。

二、const、static、static const、const static常量(变量)值的修改

本节讨论主要参考自:

http://blog.csdn.net/taotaotheripper/article/details/23712253 Ⅰ不能修改的

全局的const 、任意地方的static const不能修改。

原因:无论是否是静态,两者都是常量,显然不能通过简单的再赋值操作,即类似

static const int a=1; a=2; 的方式修改。

那么在下能想到的办法只有通过指针来修改了。

对于全局的const 、任意地方的static const,不分配内存,但一旦取地址(或是函数中return,或是将const声明为extern const,都将导致分配内存),那么在哪儿分配呢?是在常量存储区,这一区域的特点是只读,当然不能通过指针修改。例如在外部(类外、函数外的全局)写: const int a=1;

static const int b=1; 在main函数中写

int*pa=const_cast(&a);//见注释⑤ *pa=111; //(1) int*pa=const_cast(&a); *pa=111;//(2)

编译可通过,但出现运行时错误,最终可见类似

jing_tai_cheng_yuan.exe 中的 0x0106162b 处有未经处理的异常: 0xC0000005: 写入位置 0x01067830 时发生访问冲突

这样的报错。即访问非法内存,错误指向(1)、(2)两句。因为如前所说,取地址后,a被分到了只读的常量区。

Ⅱ.其它情况下的const值的修改 先看这个例子: #include using namespace std; class Chang_liang {

public:

Chang_liang(int az):a(az) {

int*pa=const_cast(&a); *pa=111;

cout<<\类的数据成员:\ cout<<\ cout<<\

cout<<\的地址:\ cout<<\的地址:\ }

void ce_shi() {

const int b=1;

int*pb=const_cast(&b); *pb=111;

cout<<\类内函数中:\ cout<<\ cout<<\

cout<<\的地址:\ cout<<\的地址:\ } private:

const int a; };

void lei_wai() {

const int c=1;

int*pc=const_cast(&c); *pc=111;

cout<<\类外普通函数中:\ cout<<\ cout<<\

cout<<\的地址:\ cout<<\的地址:\}

void main() {

const int d=1;

int*pd=const_cast(&d); *pd=111;

Chang_liang obj(1); obj.ce_shi(); lei_wai();

cout<<\函数中:\ cout<<\ cout<<\

cout<<\的地址:\ cout<<\的地址:\}

运行结果: 类的数据成员: a=111 *pa=111

a的地址:010BFA74 *pa的地址:010BFA74 类内函数中: b=1 *pb=111

b的地址:010BF988 *pb的地址:010BF988 类外普通函数中: c=1 *pc=11

c的地址:010BF994 *pc的地址:010BF994 main函数中: d=1 *pd=11

d的地址:010BFA8C *pd的地址:010BFA8C

我们可以看到,运行没有问题,指针指向的地址与数据指向的地址是一样的,指针指向的区域(也就是数据所在地址的内容)确实被修改了,(关于这一点,请看大神文章:http://www.360doc.com/content/12/0824/20/8093902_232153101.shtml )但b、c、d的输出仍然是1!这就涉及到所谓的“常量折叠”的问题。即在函数(从上例可见无论什么函数)中定义的const常量,在程序编译期间就直接替换成具体的数(如将b换成1),放到符号表中,以后凡是用到b的地方,直接用1代替,根本不经过读内存操作,所以,哪怕 对b取地址使编译器为b分配了内存,运行时b所在地址的内容确实改变了,但cout<

static修饰的变量,虽然是静态的,但毕竟是变量,满足变量的特征,(const和static const是常量,具有常量特征)存储在静态(全局)存储区(无论是静态全局变量还是静态局部变量)。所以,对static变量的值的修改,通过再赋值操作就可以了[无论什么地方(类的数据成员,各种函数中,全局)的static]。例如a=111;(a为已经初始化为1 的static int),则a被改成111,修改方法和道理与修改int a是一样的。变量的修改没有什么讨论的意义和价值,在此不再多说,也不给出示例代码。有疑问的读者,可以自己编程验证。

由于本文中多次涉及到C++的内存分配问题,所以在注释⑥中给出C++内存分配的简介,以供读者学习参考。

至此,本人的这篇文章就结束了,写得比较乱,比较杂,为此在此想读者致歉。由于本人水平有限,错误疏漏之处在所难免,希望各位读者批评指正,不吝赐教,本人将不胜感激! 谢谢!

注释①:关于extren,分两种情况简单说明: 1)在同一文件中 ??

extern const int b;//告诉编译器b将会在后面定义,否则,去掉extern, int str[b];出现error!

int str[b];//数组str ??

const int b=1;

2)在同一工程下的不同文件中

//file1.cpp //file2cpp. extern const int b; const int b; int str[b];

编译时,遇到extern const int b;,先在本文件(file1)中找有无定义的外部变量b,若有,则将其作用域扩展到本行开始,若无,则在连接时从其它文件中找有无外部变量,若有,则将另一文件(file2)中定义的外部变量变得作用域扩展到本文件。 注释②

对象的大小只与数据成员有关,成员函数放在代码区,相信学过C++的人都知道,当然,若有虚函数(无论一个或多个),对象的大小多出一个4字节的指针(该指针指向一,这不是本文讨论重点,不详述,有疑问的读者,相信您可以通过查书或百度解决 注释③

静态全局变量与静态局部变量相比,两者都储存在静态(全局)数据区,且始终驻留在该区域,直至程序结束。所不同的是作用域不同,静态全局变量的作用域是本文件,而对静态局部变量而言,当定义它的函数或语句块结束时,其作用域随之结束,尽管它还驻留在静态(全局)数据区。 注释④

无论是static conat还是const static,初始化时const都不能省,static都不能加,省const,a、b下下划线报错,类似于:Error:声明与“constfloatM元class::a”(已声明, 所在行数:15)不兼容 注释⑤

将const int* 型指针强制转换成int*型,否则会因类型不兼容而不能编译通过,const_cast是C++标准转换运算符,该句相当于C中的int* pa=(int *)(&a);可能有人要问,为什么非要强制转换呢,写成const int* pa=&a;不就行了?要知道,是不能通过const修饰的指针来改变该指针指向的值的,比如真的写成const int* pa=&a;那么* pa=111;一句中*下下划线报错:Error:表达式必须是可修改的左值。 注释⑥

在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。

栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。 里面的变量通常是局部变量、函数参数等。 相关代码执行时创建,执行结束时被自动释放。 堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。

全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的C语言中, 全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。

此时的内存在程序编译的时候已经分配好,并且在程序的整个运行期间都存在。全局变量,

static变量等在此存储。

常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改


C++中const、static、 static const和const static的初始化以及(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:河北省唐山一中11-12学年高二下学期期末考试数学文试题

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: