04C++const增强、枚举的增强
#include <iostream> int main(void)
{
//const定义常量--->const意味着只读
const int a;
int const b; // 第一个和第二个意思一样,代表一个常整数型 const int *c;//第三个 c是一个指向常整型数的指针(所指向的内存数据不能被修改,但是本身可以修改) int * const d;//第四个 d常指针(指针变量不能被修改,但是它所指向内存空间可以被修改) const int * const e;//第五个 e一个指向常整型的常指针(指针和它所指向的内存空间均不能被修改) return ;
}
1.在C语言和C++中const的表现是不同的。
先看一下const基础知识。
对const的初级理解:const是定义常量,const意味着只读。
掌握const最基本的关键点是:指针变量和它所指向的内存空间变量是两个不同的概念,看const是修饰指针本身,还是修饰了指针所指向的内存空间。
举个例子:
定义一个结构体Teacher,在operatorTeacher01函数中,函数形参 const Teacher *pt,指针所指向的内存空间不能被修改,尝试修改指针所指向的内存空间 pt->age=10 ,就会编译错误。
在operatorTeacher02函数中,函数形参 Teacher *const pt,这句话就是说pt不能被修改,也就是这个指针不能被修改,但是指针所指向的内存空间可以被修改。
再看函数operatorTeacher03(const Teacher *const pt),根据形参,这个pt指针不能被修改,指针指向的内存空间也不能被修改。
运行程序:
红色代表可修改,蓝色代表不可修改
合理的利用const的好处:
(1)指针做函数参数,可以有效的提高代码可读性,减少bug;
(2)清楚的分清参数的输入和输出特性。
如:
int setTeacher_err( const Teacher *p)
const修改形参的时候,在利用形参不能修改指针所指向的内存空间。
2、C语言中的“冒牌货”
#include <stdio.h> int main()
{
const int a = ;
int *p = (int*)&a;
print("a===>%d\n", a);//a=10 *p = ;
print("a===>%d\n", a);//a=11
//C中是只读变量,并不是真正的变量
return ;
}
#include <iostream>
using namespace std; int main(void)
{
const int a = ;//a是真正的常量
int *p = (int*)&a;
cout << "a=" << a << endl;//;a = 10
cout << "*p=" << *p << endl;//* p = 10 *p = ;//改变的是临时开辟的temp变量
cout << "a=" << a << endl;//a = 10
cout << "*p=" << *p << endl;//* p = 20
return ;
}
在.c文件中有程序:
编译就知道C语言编译器会报错,说变量a是常量,常量是不能当左值的,这样看来,好像a是定义的一个常量,不能修改!
修改程序:
定义一个指向变量a的指针变量p,通过指针修改指针p所指向位置的值,也就是a的值,编译运行:
我们发现a的值变成了20,被修改了!
也就是说我们通过指针间接修改了a的值,也就是说在c语言中const是个“冒牌货”。
同样的代码,我们运行在C++环境下:
发现运行结果跟C语言环境不同,在C++中并没有改变变量a的值。
所以,在C++中,const是一个真正的常量。
问题原因分析:
因为C++编译器对const做了加强,当C++编译器扫描到const常量声明时,它不会像C语言一样为const单独分配内存。
在C++中,int const a = 10;之后,C++编译器会将a放到一个符号表里面,符号表的存在形式:
我们定义常量a=10,key就是a,value就是10,这个值就是锁死了,不能变的,当使用a的时候,就会从符号表里面把10拿出来。
当对a变量取地址的时候,C++编译器会为a单独的开辟一块内存空间,p = (int *)&a;然后这个内存空间赋给指针p,就是p指向这个内存空间。
通过*p去间接修改的值,是这个新开辟的内存空间的值,而不是符号表中a的值,我们让*p=20、30、100…修改的都是新开辟内存空间中的值。我们可以通过打印*p去验证这两个区域并不是一回事。
结论:
C语言中的const变量
C语言中的const变量是只读变量,有自己的存储空间。
C++中的const变量
可能分配存储空间,也可能不分配存储空间;
当const常量为全局,并且需要在其它文件中使用时分配内存空间;
当使用&操作符取const常量的地址分配内存空间;
const是在编译器编译期间还是在执行阶段分配内存的?
答案:const是在编译器编译阶段分配内存的。
也就是说编译器扫描到const变量的时候就分配内存了(const变量分配内存条件参考笔记十七)。
通过程序验证:
我们知道变量a、b、c三个变量应该是连续压栈,我们打印出它们的地址,看一下b的地址是不是处于a和c之间,在a和c之间就是它们一块分配内存了,通过笔记十七已经知道对const变量取地址时才分配内存。
C++中的const修饰的是一个真正的常量
程序一:
我们知道数组的下标不能为变量,必须是一个确定的值。在C语言中看程序:
#define a 10 int main() { //第一部分 int c=; int d=; int arr[c+d]; //第二部分 //int const a=20; //int const b=10; //int arr[a+b]; return ; }
理所当然的编译错误,因为数组下标不能是变量。
在C++中看相同的程序。在C++中这点没有区别,数组下标不能为变量。同样会编译错误。
程序二:
继续在C语言中看程序修改:
//#define a 10 int main() { //第一部分 //int c=20; //int d=10; //int arr[c+d]; //第二部分 int const a=; int const b=; int arr[a+b]; return ; }
发现编译错误!错误原因跟修改前一致!
也就是说:在C语言中const定义的a、b实质并不是常量!还是变量!所以称之为“常变量”!
在C++中看相同的程序:
int main() { //第一部分 //int c=20; //int d=10; //int arr[c+d]; //第二部分 int const a=; int const b=; int arr[a+b]; return ; }
编译通过!!!
结论:
C++中的const修饰的是一个真正的常量,而不是C中变量(只读)。C++中在const修饰的常量编译期间,就已经确定下来了。
3、const 和 #define
(1)C++中的const修饰的,是一个真正的常量,而不是C中变量(只读),在const修饰的常量编译期间,就已经确定下来了;
(2)C++中的const常量类似于宏定义:const int c = 5; ≈ #define c 5
C++中的const常量与宏定义不同:const常量是由编译器处理的,提供类型检查和作用域检查;宏定义由预处理器处理,单纯的文本替换。
C语言中的const变量
C语言中const变量是只读变量,有自己的存储空间
C++中的const常量
可能分配存储空间,也可能不分配存储空间;
当const常量为全局,并且需要在其它文件中使用,会分配存储空间;
当使用&操作符,取const常量的地址时,会分配存储空间;
当const int &a = ; const修饰引用时,也会分配存储空间。
const 和 #define 的对比
第一,const与#define的相同点
C++中的const常量类似于宏定义
const int c = 5 ≈ #define c 5
const是用来替换#define的一个手段。
//程序一:
int main()
{
const int a=;
printf("a=%d\n",a);
return ;
}
//程序二:
#define a 10
int main()
{
//const int a=10;
printf("a=%d\n",a);
return ;
}
这两个程序运行结果都是一样的,都是定义一个常量a,注意#define最后是没有分号的。下面这两个程序也说明了这一点:
#define a 10
#define b 10
int main() { int arr[a+b]; system("pause"); return ; } 编译成功! #define a 10 #define b 10 int main() { int arr[a+b]; return ; } 编译成功!
第二,const与#define的不同点
看程序:
现在a是一个宏定义,我们知道宏定义,凡是变量a所在的地方预处理编译器都进行替换,也就是将a替换为10。因此在函数fun1中定义的a在函数fun2中是可以使用的,也就是说宏定义是没有作用域检查的。运行可以通过。
那么如果想将a的作用域限制在函数fun1中,可以使用“卸载宏”或者称作“取消宏” #undef 来达到目的。
#undef a —— 此处往下取消a的宏定义;
#undef —— 此处往下取消所有宏定义。
在看看const作用域检查,我们在fun1中定义变量b,其作用域就局限在fun1函数中了,在fun2函数中是不可用的,可以取消 //printf("b=%d\n",b); 的注释,发现编译时错误的!
结论:
C++中的const常量与宏定义不同
const常量是由编译器处理的,提供类型检查和作用域检查;
宏定义由预处理器处理,单纯的文本替换。
4、真正的枚举
C语言中枚举本质就是整型,枚举变量可以用任意整型赋值。而C++中枚举变量, 只能用被枚举出来的元素初始化。
#include <iostream>
using namespace std; enum season{spring,summer,autumn,winter}; int main(void)
{
enum season s = spring;
//s = 0; //error,但是C语言可以通过
s = summer;
cout << "s=" << s << endl; //
return ;
}
04C++const增强、枚举的增强的更多相关文章
- C++语言对C的增强(2)—— const增强、枚举的增强
1.const基础知识 #include <iostream> int main(void) { //const定义常量--->const意味着只读 const int a; int ...
- 增强 用文本增强修改SAP标准屏幕中的字段名称 属于元素的文本增强
如果想要改变标准屏幕中的字段名称,如把物料主数据基本数据元素的名字改为我们想要的名字 . 1.首先,事务MM03进入物料主数据的基本数据2视图中,将鼠标光标放在需要更改的字段“页格式”上,然后按F1键 ...
- PostgreSQL 10.0 preview 性能增强 - 分区表性能增强(plan阶段加速)
标签 PostgreSQL , 10.0 , 分区表 , 子表 , 元信息搜索性能增强 背景 PostgreSQL 10.0 增强了分区表的子表搜索性能,对于涉及分区表包含子表特别多的QUERY,可以 ...
- (14)jdk1.5开始的一些新特性:静态导入,增强for循环,可变参数,自动装箱/拆箱,枚举类型
Jdk1.5新特性之静态导入 jdk1.5新特性值静态导入 静态导入的作用:简化缩写 静态导入的作用:可以作用一个类的所有静态成员. 静态导入的格式:import static 包名.类名.静态的成员 ...
- 使用自定义注解和切面AOP实现Java程序增强
1.注解介绍 1.1注解的本质 Oracle官方对注解的定义为: Annotations, a form of metadata, provide data about a program that ...
- 自己实现简单的AOP(三) 实现增强四项基本功能
前面的两篇随笔,都是只是个铺垫,真正实现增强四项基本功能的重头戏,在本篇随笔中, 本文将通过AOP实现如下的四个基本功能: /// <para>1.自动管理数据库连接[可选]</pa ...
- Spring配置AOP实现定义切入点和织入增强
XML里的id=””记得全小写 经过AOP的配置后,可以切入日志功能.访问切入.事务管理.性能监测等功能. 首先实现这个织入增强需要的jar包,除了常用的 com.springsource.org.a ...
- 将表里的数据批量生成INSERT语句的存储过程 继续增强版
文章继续 桦仔兄的文章 将表里的数据批量生成INSERT语句的存储过程 增强版 继续增强... 本来打算将该内容回复于桦仔兄的文章的下面的,但是不知为何博客园就是不让提交!.... 所以在这里贴出来吧 ...
- springmvc 通过异常增强返回给客户端统一格式
在springmvc开发中,我们经常遇到这样的问题:逻辑正常执行时返回客户端指定格式的数据,比如json,但是遇NullPointerException空指针异常,NoSuchMethodExcept ...
随机推荐
- 《图解TCP/IP》读书笔记(转)
reference: https://www.cnblogs.com/edisonchou/p/5987827.html 一.国际惯例:书托 这是一本图文并茂的网络管理技术书籍,旨在让广大读者理解TC ...
- 201621123001 《Java程序设计》第11周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 一个进程可以同时运行多个不同线程,不同的线程执行不同的任务 Java线程是通过java.lang包中定义的Thre ...
- oracle用户下查看服务器或者本地IP地址
1.查看oracle所在服务器的ip: select utl_inaddr.get_host_address from dual; 2.查看登陆oracle机器的IP: select sys_cont ...
- C点滴成海------Dev C++怎么修改成简体中文
第一步:选择菜单中的Tools 第二步:选择Tools中的“Envirnoment Options”,即第二个选项 第三步:选择中文并保存 将"1"的语言改成中文就行了
- python之pandas简单介绍及使用(一)
python之pandas简单介绍及使用(一) 一. Pandas简介1.Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据 ...
- Maven Speed Up
收录架构 proxy代理仓库 不支持仓库搜索功能 收录版本 所有版本 更新时间 每24小时更新一次 使用说明 一.在maven软件中使用 以Maven 3.5.2为例: 打开maven配置文件 ./a ...
- spark:ML和MLlib的区别
ML和MLlib的区别如下: ML是升级版的MLlib,最新的Spark版本优先支持ML. ML支持DataFrame数据结构和Pipelines,而MLlib仅支持RDD数据结构. ML明确区分了分 ...
- winform 异性窗体的实现
效果图 首先需要在vs里添加控件 AlphaForm.dll 添加完了有这来两个控件 1.把第二个控件拖入窗体里把窗体铺满 2.找一张至少有一个闭合图形的透明图片 设置为AlphaFormTrans ...
- IE9中input事件与异步事件连用会发生跨域问题
IE版本中IE8以及IE9以上版本不会存在这个问题唯独IE9 发生跨域问题代码 $("#stock_code").bind("input",function(e ...
- POJ 2234 Matches Game(Nim博弈裸题)
Description Here is a simple game. In this game, there are several piles of matches and two players. ...