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 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 使用小结的文章就介绍到这了,更多相关C++11 关键字 const内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++11 constexpr使用详解

    目录 1.constexpr初探 2.constexpr修饰函数的限制 3.使用编译时对象 4.constexpr vs const的区别 C++11为了提高代码执行效率做了一些改善.这种改善之一就是:生成常量表达式,允许程序利用编译时的计算能力.假如你熟悉模板元编程,你将发现constexpr使这一切变得更加简单.constexpr使我们很容易利用上编译时编程的优势. 常量表达式主要是允许一些计算发生在编译时,即发生在代码编译而不是运行的时候.这是很大的优化:假如有些事情可以在编译时做,它将只

  • C++11关于auto关键字的使用示例

    一.概述 auto关键字在c++98中已经出现,在98中定义为具有自动存储器的局部变量, c++11中标准委员会重新定义了auto关键字,表示一个类型占位符,告诉编译器,auto声明变量的类型必须由编译器在编译时期推导 而得. 注意事项: 1.auto关键字类型推断发生在编译期,程序运行时不会造成效率降低 2.auto关键字定义时就需要初始化 3.auto仅仅是一个占位符,它并不是一个真正的类型, 因此sizeof(auto)是错误的 4.auto不能作为函数的参数 5.auto不能定义数组,如

  • 使用c++11 constexpr时遇到的坑详解

    最近在使用constexpr的时候无意中踩了个小坑. 下面给个小示例: #include <iostream> constexpr int n = 10; constexpr char *msg = "Hello, world!"; int main() { for (auto i = 0; i < n; ++i) { std::cout << msg << std::endl; } } constexpr应该是大家很熟悉的东西了,也是最常用的

  • C++11 关键字 const 使用小结

    Const 的作用及历史 const (computer programming) - Wikipedia 一.历史 按理来说,要想了解一件事物提出的原因,最好的办法就是去寻找当时的历史背景,以及围绕这件事所发生的故事. 可是非常抱歉,我并没没有找到C语言中const 提出的背景,但是一个可以参考的历史是,常量这种数据形式早在汇编语言中就有所体现,汇编语言中的constant 是一个确定的数值,在汇编阶段就可以确定直接编码在于指令代码中,不是保存在寄存器中的可以变化的量. 常量是需求,C 语言没

  • C/C++ 中const关键字的用法小结

    C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性. Const作用 NO. 作用 说明 参考 1 可以定义const常量 const int Max = 100; 2 便于进行类型检查 const常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误 void f(const int i) { ---} //对传入的参数进行类型检查,不匹配进行提示 3 可以保护被修

  • C语言关键字const和指针的结合使用

    我们先定义三个变量 1.const int *p1 2.int const *p2 3.int *const p3 p1.p2.p3这三个指针都是指向int类型的,那它们有什么区别呢 写个代码测试一下 编译一下 可看到第11,12,16行报错,从中可得出以下结论: const int * 与 int const *是一样的效果,指向的内存是不能改变的,即指针指向的内容是只读的,或者说是一个常量.不过指向的位置是可以更改的,即p1和p2可以重新指向别的常量. 而char *const 刚好相反,表

  • C语言详细分析讲解关键字const与volatile的用法

    目录 一.const 只读变量 二.const 全局变量的分歧 三.const 的本质 四.const 修饰函数参数和返回值 五.volatile 解析 六.小结 一.const 只读变量 const 修饰的变量是只读的,本质还是变量 const 修饰的局部变量在栈上分配空间 const 修饰的全局变量在全局数据区分配空间 const 只在编译期有用,在运行期无用 const 修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边. 二.const 全局变量的分歧 在现代C语言编

  • IOS 关键字const 、static、extern详解

    IOS 关键字const .static.extern详细介绍: 一.前言 阅读别人的代码(一些优秀的源码)总能发现一些常见的关键字,随着编程经验的积累大部分还是知道是什么意思的,但在概念上和具体的用法上却依然有些模糊,故特意整理汇总了下三个比较常见的关键字--const/static/extern. 二.关键字const/static/extern的释义和用法 1.const 这个单词翻译成中文是"常量"的意思.在程序中我们知道"常量"的值是不能变的,固定的.所以

  • iOS开发中关键字const/static/extern、UIKIT_EXTERN的区别和用法

    一.前言 对于刚入行的新手们这些关键字可能会经常搞混淆或不清楚它们的意思和用法吧,即使在网上看了区别,但是很久不用下次又不清楚了,而且即使清楚自己的代码恐怕也很少用起来吧.通过阅读别人优秀的代码总会发现一些常用的关键字,随着自己的编程经验的积累慢慢的明白的. 二.关键字const/static/extern/UIKIT_EXTERN的释义和用法 1.const 这个单词翻译成中文是"常量"的意思.在程序中我们知道"常量"的值是不能变的,固定的.所以const关键字的

  • c++关键字const的用法详解

    目录 C语言const的用法 1.指向常量的指针变量 const int *p指针指向int a: 2.常指针(常地址) int * const p指针指向int a; 3.指向常量的常指针 const int * const p指针指向int a; 4.其他情况 4.1 int *p指针指向const int a(报错) 4.2const int *p指针指向const int a c++语言const的用法 常数据成员 常成员函数 常对象 指向常对象的指针变量 指向对象的常指针 总结 C语言

  • 你可能从未使用过的11+个JavaScript特性(小结)

    重要 这篇文章中描述的大多数功能已被暂停使用(甚至不推荐使用). 它们仍然在许多图书中很常见,因此值得学习. 一.逗号运算符 , 是用于分隔表达式并返回链中最后一个表达式的运算符. let oo = (1, 2, 3) console.log(oo) // 3 这里有三个主要表达式 1 . 2 和 3.所有这些表达式均被求值,最后一个赋给 oo. 我们在 for 循环中看到这个: for(let i = 0, ii = 1; i< 10; i++, ii--) { ... } 当我们要编写短的

  • C++98/11/17表达式类别(小结)

    目标 以下代码能否编译通过,能否按照期望运行? #include <utility> #include <type_traits> namespace cpp98 { struct A { }; A func() { return A(); } int main() { int i = 1; i = 2; // 3 = 4; const int j = 5; // j = 6; i = j; func() = A(); return 0; } } namespace cpp11 {

  • Java的关键字与标识符小结

    本文总结了Java的关键字与标识符.分享给大家供大家参考,具体如下: 相关内容: 关键字: 定义 特点 用于定义数据类型的关键字 用于定义流程控制的关键字 用于定义访问权限修饰符的关键字 用于定义类,函数,变量修饰符的关键字 用于定义类,函数,变量修饰符的关键字 用于定义类与类之间的关系的关键字 用于定义建立实例及引用实例,判断实例的关键字 用于异常处理的关键字 用于包的关键字 其他关键字 JAVA标识符: 定义 组成规则 常见的命名规则 包 类和接口 方法.变量 常量 首发时间:2017-06

随机推荐