进化后的 const(二)

我们之前说过在 C 语言中:const 修饰的变量是只读的,其本质还是变量;它修饰的局部变量在栈上分配空间,修饰的全局变量在只读存储区分配空间;const 只在编译期有效,在运行期无用;const 修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边而已。

C 语言中的 const 使得变量具有只读属性,所以它在 C 语言中不能定义真正意义上的常量!在 C 语言中,能定义常量的只有 enum(枚举)啦。但是 C++ 在 C 语言的基础上对 const 进行了进化处理:当碰见 const 声明时在符号表中放入常量;编译过程中若发现使用常量则直接以符号表中的值替换;编译过程中若发现下述情况则给对应的常量分配存储空间:a> 对 const 常量使用了 extern,b> 对 const 常量使用 & 操作符。符号表是编译器中的一种数据结构。C++ 编译器虽然可能为 const 常量分配空间,但不会使用其存储空间中的值。那为什么还有这样做呢?是为了兼容 C 语言的特性!

下来我们以示例代码为例进行分析

#include <stdio.h>

int main()
{
    const int c = 0;
    int* p = (int*)&c;
    
    printf("Begin...\n");
        
    *p = 5;
    
    printf("c = %d\n", c);
    printf("*p = %d\n", *p);
    
    printf("End...\n");
    
    return 0;
}

我们先在 gcc 编译器编译下,应该是两个都打印 5。我们看看编译结果

结果如我们所分析的那样,因为 c 虽然是由 const 修饰的,但其本质还是变量,所以我们可以通过指针来修改它的值。下来我们用 g++ 编译器编译下看看结果会一样吗?

我们看到 c 为 0,*p 为 5。这就符合了我们之前讲的,在 C++ 中,它会将由 const 修饰的变量放入符号表中,在后面见到它会直接在符号表中进行查找,但是 *p 确实改变了,所以 *p 为 5。我们用下面这张图来具体说明

那么在 C 语言中的 const 变量是只读变量,会分配存储空间;在 C++ 中,const 就为常量了,可能会为其分配空间:a> 当 const 常量为全局,并且需要在其他文件中使用时;b> 当使用 & 操作符对 const 常量取地址;

在 C++ 中,const 常量有点就类似于宏定义了,但是它们是不一样的。const 常量是由编译器处理,编译器对 const 常量进行类型检查和作用域检查;宏定义由预处理器处理,是单纯的文本替换,并没有作用域的限制。下来我们以代码为例进行分析

#include <stdio.h>

void f()
{
    #define a 5
    const int b = 3;
}

void g()
{
    printf("a = %d\n", a);
    printf("b = %d\n", b);
}

int main()
{
    const int A = 1;
    const int B = 2;
    int array[A + B] = {0};
    int i = 0;
    
    for(i=0; i<(A + B); i++)
    {
        printf("array[%d] = %d\n", i, array[i]);
    }
    
    f();
    //g();
    
    return 0;
}

我么看到在 main 函数定义了两个 const 修饰的变量,我们用它们的和来定义数组的大小。在 C 语言中肯定是不行的,因为它们在本质上是变量,数组大小怎么可能用变量定义。但是在 C++ 中,它们就已经被放入了符号表,就为常量了。我们来看看分别用 gcc 和 g++ 编译器编译下是什么结果

我们看到用 gcc 编译器编译直接报错,但是我们用 g++ 编译器编译则通过,并且成功运行。我们再来看看 C++ 中的 const 常量和宏定义有什么区别,我们在 f() 中分别定义了宏 a 和 const b,在 g() 中进行打印。我们之前说过,宏定义是没有作用域的限制的,而 const 常量则是由作用域的,所以 b 的作用域仅为 f 函数,在 g 中打印是会出错的。我们去掉 main 函数中的第 28 行的注释,看看是什么结果

我们看到它报的是 b 没有定义。我们注释掉第 12 行,再次编译

通过实验,我们更加清晰的认识到宏定义和 const 常量的区别。通过对 C 和 C++ 中的 const 的学习,总结如下:1、与 C 语言不同,C++ 中的 const 不只是只读变量;2、C++ 中的 const 是一个真正意义上的常量;3、C++ 编译器可能会为 const 常量分配空间;4、C++ 完全兼容 C 语言中的 const 常量的语法特性。

欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083。

原文地址:http://blog.51cto.com/12810168/2112564

时间: 2024-10-09 16:56:18

进化后的 const(二)的相关文章

第3课 - 进化后的const分析

第3课 - 进化后的const分析 1. C语言中的const (1)const 修饰的变量具有只读属性,本质还是变量,只是告诉编译器该变量不能出现在赋值符号的左边. (2)const 修饰的局部变量在栈上分配空间,修饰的全局变量在只读存储区分配空间. (3)const 只在编译期间有用,在运行期间无用.const 不能定义真正意义上的常量(const英文含义)! (4)C语言中的常量只有枚举这一种类型. 2. C++中的const C++ 在 C 的基础上对 const 进行了进化处理. (1

第3课 进化后的 const分析

1.  C语言中的const (1)const修饰的变量是只读的,使得变量具有只读属性,但本质还是变量.所以不是真正的常量,它只是告诉编译器该变量不能出现在赋值符号的左边. (2)const修饰的局部变量在栈上分配空间,全局变量在只读存储区分配空间 (3)const只在编译期有用,在运行期无用 [编程实验]C/C++中的const #include <stdio.h> int main() { const int c = 0; //C语言中会为变量c分配内存 int* p = (int*)&a

sql2000数据库误删除后自行恢复二次覆盖成功恢复

sql2000数据库误删除后自行恢复二次覆盖成功恢复 [数据恢复故障描述] 今天接到一个客户电话,他的速达sql2000数据库,数据库误删除了,关键之前还没有备份过.他就想自己尝试恢复,使用网上下载的恢复工具恢复出一些数据之后,本来数据库在E盘,结果他又将恢复的数据保存在了E盘,造成了二次覆盖.结果数据库附加不上,他才意识到事情的严重性,联系到我们. 错误如图下图: [数据恢复解决方案] 工程师使用自主研发的数据库恢复软件,手工提取碎片,进行数据库碎片重组与恢复软件远程恢复成功! [数据库修复结

[Reprint]C++函数前和函数后加const修饰符区别

c++中关于const的用法有很多,const既可以修饰变量,也可以函数,不同的环境下,是有不同的含义.今天来讲讲const加在函数前和函数后面的区别.比如: 01 #include<iostream> 02   03 using namespace std; 04   05 // Ahthor:  过往记忆 06 // E-mail:  [email protected] 07 // Blog:    http://www.iteblog.com 08 // 转载请注明出处 09   10

C++ 成员函数前和函数后加const修饰符区别

博客转载自: https://www.iteblog.com/archives/214.html 分析以下一段程序,阐述成员函数后缀const 和 成员函数前const 的作用 #include<iostream> using namespace std; class TestClass { public: size_t length() const; const char* getPContent(); void setLengthValid(bool isLengthValid); pri

读《平凡的世界》后感 (二)

读<平凡的世界>后感 (二) 1.再怎么福也不能富孩子!可是,现在很多的父母亲却反了,总是在做着:"再怎么穷 也不能穷孩子",父母亲在家或外面辛勤工作,点点滴滴都很不容易,为了孩子在同龄 同学面前有面子,孩子自己也为了点面子,很多人在同学面前大摆父母亲的血汗钱! 2.发现里面提到的好书<卓娅和舒拉的故事><红岩> 3.在维特式骚动不安的年龄里:异性之间任何微小的情感,都可能在一个少年的内心掀 起狂风巨浪. 4.润叶,田晓霞:说话交流为人都一直非常非常

Jenkins 2.46 打包apk后生成下载二维码

这篇文章的前提是已经可以通过gradle构建并成功打包apk的情况下,只介绍利用"蒲公英"的应用托管平台(https://www.pgyer.com/)上传打包好的apk和在当前构建历史中生成二维码. 1.注册"蒲公英" 帐号,这个不用多说. 2.查看并记录API信息:通过右上角账户设置里查看,如图: 3.进入Jenkins安装插件:description setter plugin 其它基础的就不说了,这个是可以修改build的描述,以便生成二维码. 4.到Jen

FreeBSD从零开始---安装后配置(二)

系统优化及安全设置 上次说了FreeBSD基本的软件安装和配置,接下来会说系统的详细配置和安全性设置 一.系统优化设置 1.网络相关设置 网卡和IP地址设置: 如果在安装时没有设置IP地址,那么就需要进入系统后设置,过程如下. #cd /etc #vi rc.conf 找到ifconfig_网卡名写入(示例) ifconfig_bce0="inet 192.168.10.125 netmask 255.255.255.128" defaultrouter="192.168.1

常量函数(函数后加const)

const用在成员函数后 主要是针对类的const 对象 如: class Text{ public:     void printconst(void)const{cout<<"hello"<<endl;}     void print(void){cout<<"hello"<<endl;} private:     int k; }; const Text a; //上面定义了类Text的一常量对象 int mai