C++中const限定符
const基础
C++中的const,用于定义一个常量,这个常量的值不能被修改。因为const对象一旦创建就不能修改,所以const对象必须初始化。const常量特征仅仅在执行改变其本身的操作时才会发生作用,所以在进行其他操作时,const常量和普通变量没有区别。
它的声明方式为
void main()
{
int a;
const int b; //int型常量
int const c; //同上
const int* d; // 指针常量,d为const,指向常整型数的普通指针(所指向的内存数据不能修改,但本身可以修改)
int* const e; // 指向普通int型量的常量指针。int*为const(指针变量不能被修改,但是它所指向内存空间可以被修改
const int* const f;//指向int常量的常量指针(指针和它所指向的内存空间,都不能被修改)
}
const与指针
因为指针本身也是一个对象,所以和指针相关的const可以分为两种:
1.指针常量(pointer to const )
指针常量也就是指向常量的普通指针。也就是不能通过指针修改所指向的对象,但可以修改指针本身的指向。这里要注意的是指针常量不要求指针一定要指向一个const常量,只是指不能通过指针修改所指向的对象。它的声明形式为:
const int* d;
2.常量指针(const pointer)
常量指针是指向一个对象的常量指针。常量指针必须初始化,因为常量指针不能更改其指向。这里要注意的是普通指针(包括非常量指针和常量指针)无法绑定一个常量对象。要想指向一个常量对象,必须使用指针常量,但是指针常量所指向的对象却不一定是常量对象,这里要注意区分。为了使常量指针能够指向常量对象,于是有了指向常量的常量指针。声明如下:
int* const e; // 指向普通int型量的常量指针。int*为const(指针变量不能被修改,但是它所指向内存空间可以被修改
const int* const f;//指向int常量的常量指针(指针和它所指向的内存空间,都不能被修改)
指针常量和常量指针的区分
指针常量(pointer to const )和常量指针(const pointer)会比较容易混淆。我在网上查看时,找了一个我觉得不错的区分方法,即 “以*为中间划一条线,看const修饰谁就谁就是常量”。如,const int * d;以*划线后结果为”const int“,const修饰的是int,也就是指针所指向的对象,所以d是一个指针常量。同理对于int * const e; 划分后为const e,const修饰指针e,所以e是一个常量指针。
const的引用
不同于指针本身是一个对象,引用并不是一个对象,所以不存在常量引用,只有对常量的引用(reference to const),但是在c++中,引用一旦绑定到其他对象上,就不允许改变绑定的对象,所以引用本身具有const的特性。有的地方可能会将对常量的引用简称为常量引用,这里要知道,常量引用指的是什么。
一般要求,引用的类型必须与被引用的对象类型相同,但在有关const的引用中有例外的情况:即初始化常量引用时允许使用任意可以转换为引用类型的表达式作为初始值。例如
int i = ;
const int &r1 = i; //正确,可以将const int& 绑定到一个普通int对象
const int &r2 = ; //正确,r2是一个常量引用
const int &r3 = r1 * ; //正确,r3是一个常量引用
int &r4 = r1 * ; //错误,r4是一个普通非常量引用
能够这样初始化的原因是:对于const int &r1 = i; 这样的代码,编译器会拆解为:
const int temp = i;
const int &r1 = temp;
这里系统生成了一个临时量对象temp,然后将r1绑定在了temp上。这里很多人可能会有疑问,为什么可以将引用绑定到一个临时对象上?C++的标准规定了:当一个临时对象被绑定到一个引用时,临时对象的生命周期 >= 引用的生命周期("如果一个临时性对象被绑定于一个引用,对象将残留,直到被初始化之引用的生命期结束"(见《Inside The C++ Object Model》page275))。但必须要注意的是只有常量引用才能绑定到临时量对象。所以 int &r4 = r1 *2 ;是不能通过编译的。
类中的const
在c++类中,可能出现const的地方有:
- 常量对象
- 常量成员数据
- 常量成员函数
1.常量对象
常量对象,就是声明类的实例时加上const,如下:
const MyClass myclass;
2.常量成员数据
就是声明在类中的const数据,和在类外一样。
3.常量成员函数
常量成员函数的主要作用是可以被常量对象调用。常量成员函数的声明有两种,如下:
void func(int a) const{}; void const func(int a){};
这两种方式没有区别,它们的本质都是void func (const ClassName *this, int a); const 修饰的不是形参a,而是this(this是一个额外的隐式参数,用来访问当前对象,它的类型默认是指向类类型非常量版本的常量指针),与const所写的位置无关。因为c++对类的this指针做了隐藏,本质上,const指针修饰的是被隐藏的this指针所指向的内存空间。这里的func()函数,如果不添加const关键字,就是一个普通的成员函数,此时this的类型是ClassName* const,即this是一个常量指针,但是一般的常量指针是不能指向常量的,所以如果要使this指向一个常量对象,必须要把this定义成const ClassName* const,即指向常量的常量指针。在类成员函数的参数列表之后添加const关键字,就相当于把this定义成const ClassName* const,只有这样常量对象才能调用这个函数。
一些总结:
1)const成员函数可以访问非const对象的非const数据成员、const数据成员,也可以访问const对象内的所有数据成员;
2)非const成员函数可以访问非const对象的非const数据成员、const数据成员,但不可以访问const对象的任意数据成员;
3)常量对象只能调用常量成员函数;非常量对象可以调用常量成员函数,当const版本和非const版本的成员函数同时出现时,非const对象调用非const成员函数。
4)作为一种良好的编程风格,在声明一个成员函数时,若该成员函数并不对数据成员进行修改操作,应尽可能将该成员函数声明为const 成员函数。
作者也是一个C++的初学者,文章中难免有错误和不周到的地方,希望大家指正。
本博客参考了很多来自@CTHON https://home.cnblogs.com/u/cthon/的博文内容,十分感谢。
C++中const限定符的更多相关文章
- C++中的常量(一) const限定符
最近在重新看<<C++ Primer>>,第一遍的时候const和constexpr看得并不太懂,这次又有了些更新的理解,当然可能仍然有许多不对的地方... 首先,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对象定义之后就无法改变,所以必须对 ...
随机推荐
- centos 部署的时候安装不上Mariadb,缺少依赖文件
并不存在这个sock文件 使用systemctl status mariadb.service 查看报错信息 提示libsystemd.so.0文件不存在, 安装systemd-libs包,解决问题, ...
- [RN] React Native Fetch请求设置超时
一.实现思路 根据Promise.race的特性,我们在Promise.race里面添加两个任务,一个是正常的网络请求任务A,另外一个便是网络延时任务B,网络延时可以利用setTimeout方法实现. ...
- 从Hello World 来讲解线程
从一个经典的例子开始:一个打印“Hello World.”的程序.一个非常简单的在单线程中运行的Hello World程序如下所示,当我们谈到多线程时,它可以作为一个基准. #include<i ...
- APIO2019 游记
\(\text {Cu}\)滚粗了,滚粗选手不配拥有游记.
- nginx 日志之 error_log
Nginx错误日志平时不用太关注,但是一旦出了问题,就需要借助错误日志来判断问题所在. 配置参数格式:error_log /path/to/log level; Nginx错误日志级别 常见的错误日志 ...
- pandas把'<m8[ns]'类型转换为int类型进行运算
工作中经常碰到两列数据为date类型,当这两列数据相减或者相加时,得到天数,当运用这个值进行运算会报错:ufunc true_divide cannot use operands with types ...
- anchor_based-anchor_free object detectors
同步到知乎anchor_based-anchor_free object detectors 前言:最近关注了大量目标检测的论文,比较火的就是anchor based和anchor free两类问题: ...
- Unity3D普通开发人员,U3D主程分别需要掌握的技能
Unity3D普通开发人员 1.会查看和搜索unity API文档,熟悉一些3D术语单词 2.查看别人的代码,能够依葫芦画瓢 3.能够制作一些常见的UI效果,善用缓动类插件,如Do Tween pro ...
- python lambda表达式简单用法【转】
python lambda表达式简单用法 1.lambda是什么? 看个例子: g = lambda x:x+1 看一下执行的结果: g(1) >>>2 g(2) >>& ...
- docker 镜像制作(jupyter)
docker pull centosdocker run -it -d --name test-centos1 centosdocker exec -it test-centos1 /bin/bash ...