C++ const用法,看这一篇就够了!
本文主要介绍const修饰符在C++中的主要用法,下面会从两个方面进行介绍:类定义中使用const、非类定义中使用const
1. 非类定义中使用const
非类定义中使用const是指:在除了类定义以外的场景中使用const。
1.1 变量
const int a = 1; //定义一个常量,不可以修改
int b = 2; //定义一个普通变量,可以修改
const int &b = a; //定义一个常量引用,不可以通过引用b修改a,底层const
const int *p = &a; //定义一个普通变量,p可以修改,但是不可以通过p修改所指向的对象a,底层const
int * const q = &b; //定义一个常量指针,q不可以修改,但是可以通过q修改所指向的对象b,顶层const
const int * const s = &a; //定义一个常量指针,s不可以修改,同时不可以通过s修改所指向的对象a,靠右的是顶层const,靠左的是底层const
顶层const:变量本身是个常量
底层const:变量所指向的对象是个常量
用于声明引用的const都是底层const
1.2 函数
int fun1(const int a); //定义一个常量形参
const int fun2(int a); //等同于'int fun1(const int a);'因为函数返回的是返回值的副本
const int& fun3(int &a); //返回常量引用,不会进行对象的拷贝(注意:不要返回局部对象的引用或者指针)
const int& fun4(int a); //这实际上是一种错误的声明方式,该函数可能会返回局部对象的引用或者指针
Tips:
- 引用只是一个变量的别名,不是对象,因此引用不会占用存储空间
- 调用一个返回引用的函数得到左值,其他返回类型得到右值
2. 类定义中使用const
2.1 类成员
class Test{
public:
Test():a(10){}
void display();
private:
const int a;
};
- 类定义中不能进行初始化,因为在头文件中定义只是一个声明,并没有分配真正空间,因此变量是不存在的,因此是不能赋值的。
- 在类定义外部,const定义的变量是不能被赋值
问题:
类定义中不能赋值,类定义外部也不能赋值,但是又必须赋值,这可如何是好?
解决方案:
- 在构造函数后的参数初始化列表中初始化
- 将const变量同时声明为 static 类型进行初始化
class Test{
public:
Test():a(10){}
void display();
private:
const int a;
//static const int a;
};
//const int Test::a = 5;
2.2 类成员函数
class Test{
public:
//下面是display函数的两个重载版本
void display(); //一个普通成员函
void display() const; //一个const成员函数。
private:
const int a;
};
Tips:
成员函数都有一个额外的隐式参数this,this的值是调用该函数的对象地址,因此this是一个指针。
普通成员函数的this指针类型是:Test* const this
const成员函数的this指针类型是:const Test* const this
Test t1;
const Test t2;
t1.display(); //调用void display()
t2.display(); //调用void display() const
因为两个函数的this指针类型不同,所以display有两个重载函数。
作用:
为了在函数体内禁止修改对象,可以通过定义const成员函数来实现。
Others:
下图是截自C++ primer中的片段,请重点关注两个display函数的返回值:
display 普通成员函数的返回值是:普通引用
display const成员函数的返回值是:常量引用
造成返回值不同的原因就是:this指针类型不同

3. 参考资料
- C++ primer 第五版-P57、P201、P231、P247
- C++ non-const lvalue reference cannot bind to a temporary
C++ const用法,看这一篇就够了!的更多相关文章
- Java中的多线程=你只要看这一篇就够了
如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...
- 关于 Docker 镜像的操作,看完这篇就够啦 !(下)
紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌 ...
- JVM内存模型你只要看这一篇就够了
JVM内存模型你只要看这一篇就够了 我是一只孤傲的鱼鹰 让我们不厌其烦的从内存模型开始说起:作为一般人需要了解到的,JVM的内存区域可以被分为:线程栈,堆,静态方法区(实际上还有更多功能的区域,并且这 ...
- 【java编程】ServiceLoader使用看这一篇就够了
转载:https://www.jianshu.com/p/7601ba434ff4 想必大家多多少少听过spi,具体的解释我就不多说了.但是它具体是怎么实现的呢?它的原理是什么呢?下面我就围绕这两个问 ...
- [转帖]nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件
nginx学习,看这一篇就够了:下载.安装.使用:正向代理.反向代理.负载均衡.常用命令和配置文件 2019-10-09 15:53:47 冯insist 阅读数 7285 文章标签: nginx学习 ...
- 2019-5-25-win10-uwp-win2d-入门-看这一篇就够了
title author date CreateTime categories win10 uwp win2d 入门 看这一篇就够了 lindexi 2019-5-25 20:0:52 +0800 2 ...
- 鸿蒙应用程序Ability(能力)看这一篇就够
本节概述 什么是Ability Ability分类 Ability生命周期 Ability之间跳转 什么是Ability Ability意为能力,是HarmonyOS应用程序提供的抽象功能.在Andr ...
- windows server 2019 域控批量新增不用,只看这一篇就够了,别的不用看
windows server 2019 域控批量新增不用,只看这一篇就够了,别的不用看 1. 新建excel表格 A B C D E 姓 名 全名 登录名 密码 李 四 李四 李四 test123!@ ...
- 什么是 DevOps?看这一篇就够了!
本文作者:Daniel Hu 个人主页:https://www.danielhu.cn/ 目录 一.前因 二.记忆 三.他们说-- 3.1.Atlassian 回答"什么是 DevOps?& ...
- python面试看这一篇就够了
python-面试通关宝典 有面Python开发方向的,看这一个repo就够啦? 语言特性 1.谈谈对 Python 和其他语言的区别 Python属于解释型语言,当程序运行时,是一行一行的解释,并运 ...
随机推荐
- OA项目-表结构
############### 新建APP并配置 ############### INSTALLED_APPS = [ ... 'apps.users.apps.UsersConfig', 'a ...
- sockt-浅谈接口性能测试脚本编写
平时我们做的都是http请求的接口测试,初次接触socket接口还是有点不知如何下手,其实他如http接口请求区别并不是很大,也是接口的链接-发送数据-断开连接这三大步骤来实现: 以下文章转载自:ht ...
- php通过身份证判断性别
/** 已测试,百度很多写法不行的 * 1就是男性 2就是女性* 通过身份证获取性别类型* @param type $card* @return int*/function getCardSex($i ...
- ccpc20190823
04 http://acm.hdu.edu.cn/showproblem.php?pid=6705 分析:先把每条边以 形式放进堆,堆按路径权值从小到大排序,然后每次取出堆顶,用v的出边扩展 新的路径 ...
- baidumap 百度地图,实现多点之间的带方向路线图。
通过lastVisitAt判断时间先后. 通过三角函数验证角度 再由baidumap 会制线段 绘制三角箭头 比较难看…… 测试个人 因为框架引用baidu 有各种问题失败,为最快实现,以此页作一个独 ...
- HDU-1164-Eddy's research I(分解质因数)
由于这道题目数据范围小,所以属于水题.可以采取暴力的做法来解决. 代码如下: #include"bits/stdc++.h" using namespace std; ; ]; v ...
- java生成饼图
pom.xml文件导入依赖包 <!-- https://mvnrepository.com/artifact/org.jfree/jfreechart --> <dependency ...
- [洛谷P4720] [模板] 扩展卢卡斯
题目传送门 求组合数的时候,如果模数p是质数,可以用卢卡斯定理解决. 但是卢卡斯定理仅仅适用于p是质数的情况. 当p不是质数的时候,我们就需要用扩展卢卡斯求解. 实际上,扩展卢卡斯=快速幂+快速乘+e ...
- C语言标准库 常用函数说明
void *memset(void *str, int c, size_t n) Syntax void *memset(void *str, int c, size_t n) Description ...
- 配置Oracle10g即时客户端plsql的配置
看到网上有好多的Oracle客户端精简版本,但是这些都不是出自Oracle官方之手,难免可能会出现一些问题.经过我奋战一个小时终于搞定了这个 Oracle10g即时客户端 的配置了 1.先到Oracl ...