C++11 关键字 const 到底怎么用?
Const 的作用及历史
const (computer programming) - Wikipedia
一、历史
按理来说,要想了解一件事物提出的原因,最好的办法就是去寻找当时的历史背景,以及围绕这件事所发生的故事。
可是非常抱歉,我并没没有找到
C语言中const提出的背景,但是一个可以参考的历史是,常量这种数据形式早在汇编语言中就有所体现,汇编语言中的constant是一个确定的数值,在汇编阶段就可以确定直接编码在于指令代码中,不是保存在寄存器中的可以变化的量。
常量是需求,
C语言没理由不保留这个传统,自然而然的const关键字出现了。
二、C和C++的异同点
顾名思义,const 最基础的作用就是保证数据不会被修改,仅仅可读而已。这就好比一份没有write 权限的文件一样,只能远观而已。
const是C语言32个关键字(C++中有49个)中的一个,主要起类型修饰的作用,可以理解为变量的属性,比方说const int a = 10从右往左看int a = 10是定义并初始化了一个变量a等于10,随后使用const 修饰这个变量,告诉编译器,这个变量是不可修改的。为了维护程序的安全性,由于const一旦修饰就无法再更改了,那么const int a;会生成一个值随机且永远无法修改的量,这样非常不安全,所以C的编译器会要求你必须在定义的时候就立马初始化。从这里也可以看出const关键字的强硬之处。
到底const该放在哪?
在详细讨论const的用法之前,必须首先明白,
const是C语言中的一个类型限定符(type quailier),是类型的一个部分,且const越靠近谁,就修饰谁是常量类型。
从C语言的基础数据类型来看,基本上可以抽象为一下几个类别
基础数据类型(整型,浮点)
- 对于基础数据类型,使用const就单纯定义为一个不可修改的量,此时由于不涉及其他的类型限制符,所以
const放在哪里都是有效的 const int i = 10\(\Leftrightarrow\)int const i = 10但是一般const在前。
- 对于基础数据类型,使用const就单纯定义为一个不可修改的量,此时由于不涉及其他的类型限制符,所以
指针类型(指针)
- 相比于基础数据类型,指针类型存在很大的不同。
不使用
const修饰的指针,此时表示该指针一定指向一个变量,当指向const修饰的变量是就会报错const int a = 10;
int * ptr = a; // error
当
const放在int *前时,表示指针类型是const int类型,那么依据指针类型的定义,该指针必定指向一个const int类型的量,即常量。const int b = 100;
const int * a = &b;
当
const放在int *后面时,int * const a,显然根据常规的指针类型的定义,我们只能推测出这是一个指向int类型的指针,那么const起什么作用呢?(见如下代码)int c = 10, b = 20;
const int b = 30;
int * const a = &c; // 此处没有报错,证明*号前面是指针类型,这条真理没错
//1. 可当我们尝试修改指向的时候
a = &b;
// 此处会报错!这表明const靠近变量名的时候表示指针指向一个变量后就无法更改了 //2. 如果一开始就不初始化int * const a呢?
int * const a; // 此处会报错 //3. 如果尝试让他指向一个const量呢?
int * const a = &b; // 此处会报错
以此类推可以得到一个指向const变量的无法修改指向的指针
const int b = 10;
const int * const a = &b;
所以可以给出总结
const靠近变量名的时候表示指针必须指向一个类型与指针类型相同的变量- 一旦指向就无法更改指向
- 无法指向常量
复杂数据类型(枚举,结构,共用)
针对复杂类型,由于出现了简单类型的嵌套,自然会有
const的嵌套关系,下面以结构体来举例子- 当
const嵌套在结构体内部时。
typedef struct a {
const int b;
int c;
}A; int main() {
A aa;
aa.b = 10; // 此处会报错
}
在C语言中,在结构体内部使用const修饰不会报错的,但是此变量再也无法修改,意味着这是一个无效量,既无法初始化,也无法修改(但是得益于C++的面向对象机制,即使如此我们还是可以定义
const并且给他赋值)。- 当定义结构体的时候使用
const
const A bb;
此时也会报错,而且相对来说比上面还严重,此时结构体内部的所有值都是乱的,且无法修改。
- 当
而C++中由于引入了几种新的编程模式,const 的作用范围又进一步被扩充。
类中属性与成员函数
- 结构体的遗留问题(即类的常量属性)
这里先来解决前面C语言中的结构体问题,需求是想在结构体内部定义const变量,知道结构体内部的变量是无法直接初始化的,而C++中结构体可以理解为类,只不过权限不同而已,同样可以拥有构造函数。
那么是不是可以在构造函数中初始化呢?(下面代码会报错)
struct a {
a() {
b = 100;
}
const int b;
};
不是我们想的那样,不过也非常接近,对于初始化类的变量还有一种方法,使用初始化列表(类的初始化列表的优先级是非常高的)
struct a {
a() : b(100) {;} const int b;
};
或者还有
struct a {
const int b = 100;
};
利用C++特性直接赋值,而此段代码在C语言中会报错,这也是C与C++不同的一个地方。
如此就完美解决了结构体
const量 问题。- 类的静态变量vs
const变量
static也是一个修饰符,确定的是变量的生存期。const觉得变量的可读性,有这样一条语句在类中和main函数中存在不同的意义static const int a;
// 此语句在main中会报错,由于未初始化
// 在类中不会
这是由于static不会影响const的表达,在main函数中说明此变量就是const类型,确实需要立马赋值。而在类中可以不那么着急,可以把类中的static变量理解为一个申明,在类的外面或者里面直接定义都可以,不会报错。
- 函数
const以及类成员函数的const修饰
普通函数的
const函数
const首先想到的是const 变量返回值。但是这其实是没太大意义的const修饰返回值其实完全没有发挥作用,属于无效修饰。同样的使用const修饰形式参数的时候也是如此,并不会限定你传入的是const还是普通变量,本质在于这一过程发生原因是由于值传递,不论是返回const还是使用const修饰形式参数,内部都发生了变量的创建与赋值那
const修饰形参的例子,int fun(const int a) {
// a = 10 会报错
return a
} int main() {
int c = 10;
int d = fun(c); // 不会报错
}
如上,c传入的时候是把c的值拿到,然后函数压栈,创建一个
const int变量a且立马初始化为c的值,如此就在函数内部生成了一个const变量。跟传入什么值完全没有关系。成员函数的
const尾修饰这属于C++的特性,成员函数尾巴加上一个
const限制此函数对对象的修改,且提高了代码的可读性。class A {
private:
int a; public:
static int B;
int getA() const {
A::B = 100; // 此处不会报错
a = 100; // 这里会报错
return a;
}
}; int A::B = 100;
使用
const修饰成员函数会使该函数变成const member function此类型无法修改对象的数据,但是可以修改可修改的静态变量。引用
引用相对来说没有指针那么多的变种,引用的
const修饰也仅仅局限于让引用变量无法修改指向这一点上。在补充一点
const修饰类静态整型变量的时候可以在类内部直接初始化(浮点数仍然是不行的)。
C++11 关键字 const 到底怎么用?的更多相关文章
- 关键字const
const关键字常和指针一起使用. 1,const给读代码的人传达非常有用的信息.比如一个函数的参数是const char *,你在调用这个函数时就可以放心地传给它char *或const char ...
- C语言关键字const作用及其应用
只要学过C语言的,都有知道const这个关键字,知道是用来定义常量的,如果一个变量被const修饰,那么它的值就不能再被改变,那么还有什么其他作用呢? 一.const常用作用 1.修饰局部变量 con ...
- ES6中不得不说的关键字const
上一节讲了let关键字,它是用来声明一个变量,只在块级作用域起作用.这一节我们来学习ES6新增的另一个关键字const. const 的作用 const是constant(常量)的缩写,const和 ...
- C++ 11 关键字
1.auto 我现在用auto,基本是在变量定义时根据初始化表达式自动推断该变量的类型. 另外与关键字 decltype 连用,在声明或定义函数时作为函数返回值的占位符. auto不能用来声明函数的返 ...
- final关键字+const关键字
final关键字 1.如果我们希望某个类不被其它的类来继承(可能因为安全考虑),可以使用final. 例题 <? final class A{} class B extends A{};//会报 ...
- 关键字 const
如果关键字出现在星号左边,表示被指物是常量: 如果出现在星号右边,表示指针本身是常量: 如果出现在星号两边,表示被指物和指针都是常量. void f1(const Widget* pw); //f1和 ...
- C# 关键字const与readonly的区别
尽管你写了很多年的C#的代码,但是可能当别人问到你const与readonly的区别时候,还是会小小的愣一会吧~ 笔者也是在看欧立奇版的<.Net 程序员面试宝典>的时候,才发现自己长久以 ...
- js-变量定义关键字const,var,let
1.var定义的变量可以修改,如果不初始化会输出undefined,不会报错. js中最常用的关键字:基本大多数据学js时都只看到使用过var.从没相关还有其他定义 var a = 1; // var ...
- 如何使用C#关键字const,readonly,static
如果有一个值不太会变化,我们经常使用const和readonly,这2者有何不同呢?有时候,我们也会在readonly之前加上关键字static,这又意味着什么呢? const ● const默认是静 ...
随机推荐
- 介绍一款docker管理工具——portainer
介绍一款docker管理工具--portainer 目录 介绍一款docker管理工具--portainer 1.背景 1.1 管理docker方法上一般有两种 1.1.1 命令行形式 1.1.2 U ...
- [luogu6838]网络站点
先分析答案,即$x$和$y$的关系有以下两种: 1.$y$在$x$子树中,那么答案即为包含$y$的$x$的儿子 2.$y$不在$x$子树中,那么答案即为$x$的父亲 那么第一个问题就是判断$y$是否在 ...
- [nowcoder5668J]Operating on the Tree
考虑令$a_{i}$为i的位置,$p_{i}=0/1$表示第i个点的贡献,那么$p_{x}=0$当且仅当存在与其相邻的点$y$满足$a_{y}<a_{x}$且$p_{y}=1$ 树形dp,定义状 ...
- [loj3274]变色龙之恋
首先有一个暴力的做法,将任意两个点判断,可以得到与之相关的1或3只变色龙:1只是两只变色龙相互喜欢,那么剩下那只就是颜色相同:3只从3只选2只并和自己判断一次,结果为1的那次剩下的那个就是他喜欢的,然 ...
- 【Microsoft Azure 的1024种玩法】六、使用Azure Cloud Shell对Linux VirtualMachines 进行生命周期管理
[文章简介] Azure Cloud Shell 是一个用于管理 Azure 资源的.可通过浏览器访问的交互式经验证 shell. 它使用户能够灵活选择最适合自己工作方式的 shell 体验,本篇文章 ...
- bsp工程管理
1. bsp工程管理的目的 模块化项目,使得项目清晰 2. 代码 拷贝原来工程 创建文件夹 bsp就是工程驱动文件 imx6ull是和芯片有关的文件 obj是生成文件的文件夹 project 工程文件 ...
- 论文翻译:2020_A Recursive Network with Dynamic Attention for Monaural Speech Enhancement
论文地址:基于动态注意的递归网络单耳语音增强 论文代码:https://github.com/Andong-Li-speech/DARCN 引用格式:Li, A., Zheng, C., Fan, C ...
- CF1437G Death DBMS
题面传送门. 题意简述:给出 \(n\) 个字符串 \(s_i\),每个 \(s_i\) 初始权值为 \(0\).\(q\) 次操作:修改 \(s_i\) 的权值:查询给出字符串 \(q\) 能匹配的 ...
- UE4之Slate: SImage
概述 距离上次记录<UE4之Slate:纯C++工程配置>后已经好长时间了: 这个随笔来记录并分享一下SImage控件的使用,以在屏幕上显示一张图片: 目标 通过SImage控件的展示,学 ...
- 振鹏学习Java的第二天!
一.今日收获 1.了解了eclipse的具体使用方法. 2.学习了Java程序设计完全手册的第一章内容,明白了相关知识. 3.通过看哔哩哔哩的java的教程视频了解了Dos命令及java的变量和常量. ...