[C/C++]const限定符总结
const限定符
const是一种限定符,被const所限定的变量其值不可以被改变。
const的初始化
由于const一旦创建其值就不能够被改变,所以我们必须对其进行初始化
const int a;//错误,const变量必须进行初始化!
const int b=10;//正确,编译时初始化
const int c=get_size();//正确,运行时初始化
相同类型的变量相互初始化时,不论变量是否被const限定我们都可以进行随意的相互拷贝。因为在拷贝过程中我们只会用到等式右边变量的右值属性,无须在意其是否可以改变。
int m = 5;
const int n = m;
int j = n;
const与指针
顶层const与底层const
对于指针来说,由于其指向另一片内存的特点,有三种不同的const情况,即:
- 指向常量的指针(const int *)
- 常量指针(int * const)
- 指向常量的常量指针(const int *const)
我们一般称符合第一种情况的为具有底层const属性。
符合第二种情况的为具有顶层const属性。
第三种情况兼而有之。
关于带有const的指针的相互赋值(或者初始化)问题
- 顶层const并不会影响变量间的相互拷贝(原因是顶层const只保证自身的值不会改变,const没有改变自身的变量类型,在拷贝时只是使用该类型的右值)。
- 如果等号右边是底层const,那么等号左边必须保证为相同的底层const(或者等号右边的类型可以转换成等号左边的类型),否者表达式无法通过编译。
关于底层与顶层const的一些想法
const的底层与顶层属性似乎只在指针上存在。但是c++primer中有这样的代码和注释:
const int ci=1,&cr=ci;
auto b=ci;//b是一个整数(ci的顶层const特性被忽略掉了)
auto c=cr;//c是一个整数(cr是ci的别名,ci本身是一个顶层const)
这段代码是为了说明auto说明符一般会忽略掉顶层const的特性,在注释中明确写着ci本身是一个顶层const。
这也与我的看法一致,底层与顶层const实际上并不是指针所特有的,只要是不能改变对象自身的对象都具有顶层const,而不能改变自己所指向的对象的对象都具有底层const。
从这个角度看,引用实际上自带顶层const。
底层const的隐式转换
上面提到,只有在等号右边和等号左边的类型具有相同的底层const属性,才可以进行赋值或者初始化。
然而有些时候等号右边可能并不具有和等号左边一致的底层const却依然可以成立,这是因为等号右边的类型发生了隐式转换从而具有了和等号左边类型相同底层const属性。
例如:
int i=5;
int *p=&i;
const int *cp=p//int*隐式转换称为了const int*
为什么int *转换成const int *被设定为合法的呢,因为在将int *转换为const int *的过程中用户的权限变小了,在这一转换过程中并不会使程序变得不可靠。
由此我们可以得知非底层const的指针是可以通过隐式转换转变成底层const的。
const与引用
可以把引用绑定在const的变量上,称为const的引用,对常量的引用。
与普通的引用不同的是,对常量的引用不能被用作修改它所绑定的对象
const int ci=5;
const int &r=ci;
r=6//错误不可以通过常引用来修改值
int &r2=ci//错误,试图让一个非常量引用指向一个常量对象。
const引用的初始化
我们知道对于引用来说初始化时一定要用一个对象初始化,且该对象的类型需要与之匹配。
但是const的引用是个例外,在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可,甚至允许为一个常量引用绑定非常量的对象、字面值或者是表达式。
int i=42;
const int &r1=i;//允许将const int&绑定到一个普通int对象上
const int &r2=3.14;//正确:r2是一个常量引用
const int &r3=r1*2;//正确:r3是一个常量引用
int &r4 =r1*2;//错误,非常量引用不能用表达式初始化。
C++primer中给出了可以这么做的原因:
要想理解这种例外情况的原因,最简单的方法是弄清楚当一个常量引用被绑定到另外一种类型上都时到底发生了什么:
double dval=3.14;
const int &ri=dval;
此处ri引用了一个int型的数。对ri的操作应该是整数运算,但dval却是一个双精度浮点数而非整数。因此为了确保让ri绑定一个整数,编译器把上述代码变成了如下形式:
const int temp=dval;//由双精度浮点数生成一个临时的整型常量
const int &ri=temp;//让ri绑定这个临时量
在这种情况下,ri绑定了一个临时量对象。所谓临时量对象就是当编译器需要一个空间来暂存表达式的求值结果时临时创建的一个未命名的对象。C++程序员们常常把临时量对象简称为临时量。
const与auto类型说明符
auto类型说明符是C++11中新引入的类型说明符,可以自动推断类型。
编译器推断出来的auto类型有时候和初始值的类型并不完全一样,编译器会适当的改变结果类型使其更符合初始化规则。
auto在推断带有const的对象时,编译器一般会忽略掉顶层const,同时底层const则会保留下来。
另外对于引用由于引用没有真正的实体,所以如果用一个引用来初始化auto类型时,auto实际上为引用所指向的对象的类型,而非引用,如果要说明其为引用类型,需要使用auto&。
const int ci=i,&cr=ci;
auto b=ci;//b是一个整数(ci的顶层const特性被忽略掉了)
auto c=cr;//c是一个整数(cr是ci的别名,ci本身是一个顶层const)
auto d=&i;//d是一个整型指针(整数的地址就是指向整数的指针)
auto e=&ci;//e是一个指向整数常量的指针(对常量对象取地址是一种底层const)
如果希望推断出的auto类型是一个顶层const,需要明确指出:
const auto f=ci;//ci的推演类型为int,f是const int。
[C/C++]const限定符总结的更多相关文章
- C++const限定符
在C语言中我们使用#define宏定义的方式来处理符号常量.而在C++中有一种更好的处理符号常量的方法,那就是使用const关键字来修改变量声明和初始化.这种处理常量方式的好处不言而喻:如果程序在多处 ...
- const 限定符
1.定义const对象 const限定符把一个对象转换成一个常量 const int Bufsize = 512; 定义Bufsize 为常量并初始化为512.变量Bufsize仍然是一个左值,但是不 ...
- C++杂谈(一)const限定符与const指针
const限定符 c++有了新的const关键字,用来定义常变量,可以替C语言中的#define.关于const限定符,有以下需要注意: 1.创建后值不再改变 2.作用范围在文件内有效 3.添加ext ...
- C++ Primer 第二章 引用 指针 const限定符
1.引用: 为对象起了另外一个名字,引用类型引用另外一种类型,通过将声明符写成&d的形式来定义引用类型,其中d也就是声明的变量名(声明符就是变量名). PS:1.通过图片中编译所提示的报错信息 ...
- 指针和Const限定符
指针和Const限定符 1.指向const对象的指针 如果指针指向的是const对象,则不允许使用指针来改变其所指的const值.C++要求指向const对象的指针具有const特性. const d ...
- C++ const 限定符
C++ const 限定符 作用:把一个对象转换成一个常量 用法:const type name = value; 性质:1. 定义时必须初始化,定义后不能被修改.2. 类中的const成员变量必须通 ...
- const限定符的作用
const限定符的作用: 1.定义const常量:const可以将一个对象变成一个常量,不可被修改,所以定义的 时候必须进行初始 ...
- C++之const限定符
作者:tongqingliu 转载请注明出处: C++之const限定符 const初始化 const的特点: 用const加以限定的变量,无法改变. 由于const对象定义之后就无法改变,所以必须对 ...
- 变量和基本类型——复合类型,const限定符,处理类型
一.复合类型 复合类型是指基于其他类型定义的类型.C++语言有几种复合类型,包括引用和指针. 1.引用 引用并非对象,它只是为一个已存在的对象所起的另外一个名字. 除了以下2种情况,其他所有引用的类型 ...
- C++之const限定符(顶层const,底层const)
作者:tongqingliu 转载请注明出处:http://www.cnblogs.com/liutongqing/p/7050815.html C++之const限定符(顶层const,底层cons ...
随机推荐
- Spring AOP 基于AspectJ
简介 AspectJ是一个基于Java语言的AOP框架,Spring2.0以后新增了对AspectJ切点表达式支持.因为Spring1.0的时候Aspectj还未出现; AspectJ1.5中新增了对 ...
- 基于Arduino的红外遥控
1.红外接收头介绍 一.什么是红外接收头? 红外遥控器发出的信号是一连串的二进制脉冲码.为了使其在无线传输过程中免受其他红外信号的干扰,通常都是先将其调制在特定的载波频率上,然后再经红外发射二极管 ...
- 使用内存映射文件MMF实现大数据量导出时的内存优化
前言 导出功能几乎是所有应用系统必不可少功能,今天我们来谈一谈,如何使用内存映射文件MMF进行内存优化,本文重点介绍使用方法,相关原理可以参考文末的连接 实现 我们以单次导出一个excel举例(csv ...
- 用Python爬取了考研吧1000条帖子,原来他们都在讨论这些!
写在前面 考研在即,想多了解考研er的想法,就是去找学长学姐或者去网上搜索,贴吧就是一个好地方.而借助强大的工具可以快速从网络鱼龙混杂的信息中得到有价值的信息.虽然网上有很多爬取百度贴吧的教程和例子, ...
- 1z0-062 题库解析4
题目: Examine this parameter: NAME TYPE VALUE ------------------------ -- ...
- 重拾c++第三天(5):循环和关系表达式
1.改变步长 ;i<;i=i+) 2.*与++优先级相同,从右向左 3.strcmp函数比较两个字符串,=0两个相同,><0 ----> str1><str2 4. ...
- 使用rabbitmq手动确认消息的,定时获取队列消息实现
描述问题 最近项目中因为有些数据,需要推送到第三方系统中,因为数据会一直增加,并且需要与第三方系统做相关交互. 相关业务 本着不影响线上运行效率的思想,我们将增加的消息放入rabbitmq,使用另一个 ...
- cogs 49. 跳马问题 DFS dp
49. 跳马问题 ★ 输入文件:horse.in 输出文件:horse.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 有一只中国象棋中的 “ 马 ” ,在半张 ...
- Pyhon语法字符集报错
pyhton对语法的字符集,特别的敏感因此我们在写python代码特别要注意.以下代码是个人在学习python中遇见的错误 附:错代码截图1-1 从以上代码中可以看到,似乎代码没有什么问题接下来验证一 ...
- 13.系统总结static
static修饰属性和方法: package com.oop.demo08; //static :被static修饰的变量或者方法随类加载,从属于类,当然对象也可以调用 public class St ...