C++系列:const关键字

这篇具有很好参考价值的文章主要介绍了C++系列:const关键字。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在学习C++时,const关键字的知识点分散在书的各个章节。当我们尝试在编程时使用const时,总会感觉有一些细节被遗忘,因而不能得心应手地使用const关键字。因此,本篇文章尝试着对const关键字的做一些总结。参考书籍《C++ Primer Plus》

const总结

这里是我做的关于const关键字的一些总结,之后的各章便是对书中知识点的理解。

  • const限定符创建的常量不可再次修改
  • 创建常量时记得初始化
  • const创建的常量可以用来声明数组长度。
  • const int * p;p指向常量,p可修改,*p不可修改。
  • int * const p;, p指向变量,p不可修改,*p可修改。
  • const指针可以接受const数据和非const数据。
  • const指针仅可以接收非const数据。
  • 不允许将非const指针的地址赋值给const指针。
  • const引用创建临时变量的两种情况。
  • const全局变量是内部链接性,如static。可用extern更改链接性。可在头文件中使用。
  • cv-限定符。
  • const成员函数,void show() const;,表示函数不会修改调用对象(类成员)。

const限定符

const关键字是C++中较为常用的一个关键字。当我们想创建一个符号常量时,按照C语言的习惯,我们一般会使用#define这种预处理器方法,例如#define ZERO 0。但在C++中,提供了一种更好的处理符号常量的方法,那就是const关键字。

创建常量

创建一个常量的通用格式:const type name = value;
例如:

const int zero = 0; // 一个普通的常量·

这个例子中,被const修饰过的变量zero会变为常量。常量zero被初始化后,其值就被固定了,C++编译器不允许再次修改常量的值。

常量初始化

这里有一点需要注意:在用const声明一个变量时,需要进行初始化。例如下面的代码是错误的:

const int zero;//声明常量时需要进行初始化,否则zero的值未知。
zero = 0;//因为C++编译器不允许再次修改常量的值。所以此处错误。

另外,常量可以用来作为声明名数组时的元素数目。例如:

const int ten = 10;//创建了一个常量。
int array[ten];//用常量创建数组。

一级指针与const

在用const修饰指针时则会出现一些很微妙的地方。在C++中,可以用两种不同的方式将const关键字用于指针。第一种方法是让指针指向一个常量,第二种方法是让指针本身就是常量。其中,第一种方法可以防止使用该指针来修改所指向的值。而第二种方法可以防止改变指针所指的位置。例如:

int value = 0;
const int * p1 = &value; //第一种用法,防止利用p1修改value的值。
int * const p2 = &value; //第二种用法,p2本身不能再修改了。

这里有一个特殊情况令人在意。如果将一个指向变量的指针指向一个常量会发生什么?代码如下:

const int value = 0;
int * p2 = &value; //这是错误的,C++禁止这样的行为。

我们发现,value是常量。但p2是指向value的,那么我们可以通过* p2value的值进行修改。可是做这样的话const的作用就失效了。
事实上,C++禁止这样的用法。也就是说,C++禁止将const常量的地址赋值给非const指针。因此,上面的代码是错误的。在逻辑上也很好解释。
我们可以这样理解:为保证常量不可再次修改的属性,我们不能通过指针修改常量,因此,非const指针仅可以接收非const数据。与之类似,因为我们声明了const指针目的是不会通过当前指针修改其指向的数据,因此其指向的数据一直都是安全的,自然const数据和非const数据都可以。因此,const指针可以接受const数据和非const数据。

二级指针使用const的限制

关于二级指针与常量的关系有些复杂,我们来看下面的代码:

const int ** pp;//这是一个二级const指针
int *p;
const int value = 0;//这是一个常量
pp  = &p;  //这里是错误的,虽然高亮没有提示错误。
           //错误C2440:初始化:无法从int **转换为const int **。
*pp = &value;//两个都是常量,赋值没有问题
*p  = 10; //通过p修改了value的值!

如果pp = &p允许的话,那么我们可以通过二级指针绕开const的限制,如上诉代码一样。C++规定,仅当且只有一层间接关系(如指针指向基本数据类型)时,才能将非const地址赋值给const指针。也就是说,C++不允许将非const指针的地址赋值给const指针。
最后,关于const与指针的关系,下面还有几个例子,请看:

const int value =0;//这是常量
const int *p1;//p1可变,*p1不可变
int * const p2 = &value;//p2不可变,*p2可变

const int ** pp3;//pp3可变,*pp3可变,**pp3不可变
int * const * pp4;//pp4可变,*pp4不可变,**pp4可变
int ** const pp5;//pp5不可变,*pp5不可变,**pp5可变
const int * const *const p6 = &p1;//pp6不可变,*pp6不可变,**pp6不可变

const引用

我们在使用函数的时候,一般会使用引用形参。原因就是因为速度快,无需走复制的流程。当我们使用引用的时候,如果实参与引用参数不匹配,那么C++将产生临时变,关于const引用却有需要了解的知识点。
如果引用形参是const,则C++编译器将在下面两种情况下生成临时变量:

  • 实参的类型正确,但不是左值。
  • 实参的类型不正确,但可以转换为正确的类型。

左值:在C语言中,左值最初指的是可出现在赋值语句左边的实体,但现在,常规变量和const变量都视为左值,因为可以通过地址访问它们。
左值例子:变量,数组元素,结构成员,引用,解除引用的指针等。
非左值例子:字面常量(用引号括起的字符串除外,因为它们是地址),包含多项的表达式等。

代码例子如下:

double refcube (const double &ra){return ra * ra * ra;}
double side = 3.0;
long edge = 5L;

double x1 = refcube(edge);//实参类型不正确,但可以转换为正确的类型
double x2 = refcube(7.0);//实参类型正确,但不是左值(字面常量)
double x3 = refcube(side+10.0);//实参类型正确,但不是左值(表达式)

const全局变量

在C++中,const限定符对默认存储类型稍有影响。默认情况下,C++全局变量的链接性是外部的,但const全局变量的链接性为内部的。也就是说,在c++看来,全局const定义就像使用了static说明符一样。
C++这样做有着很多的好处,这意味着每个文件都有自己的一组常量,而不是所有文件共享一组常量。因此我们可以将常量定义到头文件中,这样只要在两个源代码文件中包括同一个头文件,则它们将获得同一组常量。当然,如果我们希望某个常量的链接性为外部的,那么我们可以使用extern关键字来覆盖默认的内部连接线。extern const int states = 50;

cv-限定符

  • const
  • volatile
    const限定符表明,内存被初始化后,程序便不会再对它进行修改。
    volatile限定符表明,即使程序没有对内存单元进行修改,但其中的值也可能发生变化。可能由于硬件的原因,也可能由其他程序修改,如共享数据。这个关键字的作用主要是为了改善编译器的优化能力。
    防止编译器将该值用缓存的方式进行优化。
    mutable限定符也是需要了解的。当我们声明一个数据结构体为常量,而其中某个成员却需要修改时。我们可以利用mutable限定符对需要修改的成员加以修饰。例子如下:
struct Data{
int x;
mutable int y;//声明此成员是可被再次修改的。
};
const Data data = {1,2};//data实例是常量
data.y=3;//但data的y成员可以被再次修改!

上述代码中,dataconst禁止程序修改data的成员,但由于y成员的mutable限定符说明了datay成员不受这种限制,仍然可以被再次修改。

const成员函数

请看如下的代码片段:

class Data{
int x;
public:
void show(){std::cout <<x;};
}
//
const Data data = {1};
data.show();//这里会报错哦!

C++编译器在data.show();会报错,因为show();函数无法确保调用对象不被修改。很有可能show函数修改了data中的成员,因此C++编译器为了保证data不会被再次修改,禁止了这种调用行为。在C++中,解决这类问题的办法是const成员函数。
请看下面的代码:

class Data{
int x;
public:
void show() const {std::cout <<x;};//这里的const!
}
//
const Data data = {1};
data.show();//这里不会报错了

对于show()的声明应该类似于这样:void show() const;
对于show()的定义应该类似于这样:void Data::show() const {...}
这种方式声明和定义的类函数被称为const成员函数,const成员函数表示函数不会修改调用对象(类成员)。
最后,本人才疏学浅,可能会有很多错误,还望诸君见谅。文章来源地址https://www.toymoban.com/news/detail-837613.html

到了这里,关于C++系列:const关键字的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 在C++和C中static关键字的用法,在C++和C中const关键字的用法

    1、在C++和C中static的用法 答:static表示存储类型,修饰数据类型。在C语言中,static修饰局部变量,内存分配在静态区,生命周期延长,作用域不变。static修饰全局变量,内存分配在静态区,作用域被局限于本文件,不能被extern引用。static修饰函数,不能被exter

    2024年02月10日
    浏览(12)
  • 【C++】const、static关键字和构造函数初始化

    【C++】const、static关键字和构造函数初始化

    💗个人主页💗 ⭐个人专栏——C++学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 1. const修饰成员函数 1.1 语法格式 1.2 权限放大缩小 1.3 思考 1.4 解答 2. 再谈构造函数 2.1 构造函数体赋值 2.2 初始化列表 2.3 explicit 3. static成员 3.1 静态变量 3.2 静态函数 3.3 静态成员变量

    2024年02月19日
    浏览(13)
  • 【C++】C 语言 和 C++ 语言中 const 关键字分析 ( const 关键字左数右指原则 | C 语言中常量的原理和缺陷 | C++ 语言中常量原理 - 符号表存储常量 )

    【C++】C 语言 和 C++ 语言中 const 关键字分析 ( const 关键字左数右指原则 | C 语言中常量的原理和缺陷 | C++ 语言中常量原理 - 符号表存储常量 )

    【C 语言】const 用法 ( 常量指针 - const 在 * 左边 - 修饰数据类型 - 内存不变 | 指针常量 - const 在 * 右边 - 修饰变量 - 指针不变 ) 普通类型数据的常量定义时 , const 在 数据类型 的 左边 和 右边 其作用 是相同的 ; 指针数据的相关常量类型 : const 在 指针符号

    2024年02月11日
    浏览(11)
  • C++ -- 学习系列 static 关键字的使用

    C++ -- 学习系列 static 关键字的使用

    static 是 C++ 中常用的,被 static 修饰的变量只会在 静态存储区 (常量数据也存放在这里) 被分配一次内存,生命周期与整个程序一样,随着程序的消亡而消亡。 1. 在文件中定义的 静态全局变量 2. 在函数中定义的静态变量 3. 类的静态成员变量 4. 静态类对象 5. 类的静

    2024年02月09日
    浏览(11)
  • C++面试八股文:static和const的关键字有哪些用法?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第7面: 面试官:C++中, static 和 const 的有哪些用法? 二师兄: satic 主要用在以下三个方面:1.用在全局作用域,修饰的变量或者函数为静态的,限制在本文件内使用。2.方法内修饰修饰静态局部变量,在第一次访问

    2024年02月08日
    浏览(13)
  • 关于c++中mutable、const、volatile这三个关键字及对应c++与汇编示例源码

    这哥三之间的关系是有趣的,不妨看看这个: cv (const and volatile) type qualifiers - cppreference.com permits modification of the class member declared mutable even if the containing object is declared const. 即便一个对象是const的,它内部的成员变量如果被mutable修饰,则此成员变量依旧可以被修改。 很常见,

    2024年02月13日
    浏览(43)
  • 【C++干货基地】面向对象核心概念 const成员函数 | 初始化列表 | explicit关键字 | 取地址重载

    【C++干货基地】面向对象核心概念 const成员函数 | 初始化列表 | explicit关键字 | 取地址重载

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 : 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活!   哈喽各位铁汁们好啊,我是博主鸽芷咕《C++干货基地》是由我的襄阳家乡零食基地有感而发,不知道各位的城市有没有这种实惠又全面的零食基地呢?C++ 本身作

    2024年04月23日
    浏览(14)
  • 详解const、static关键字

    详解const、static关键字

    目录   一、static 二、const 在c语言中: static是用来修饰变量和函数的         1.修饰局部变量——称为静态局部变量         2.修饰全局变量——称为静态全局变量         3.修饰函数——称为静态函数 有关内存相关知识补充: 程序的所有数据,也就是所有的

    2024年02月06日
    浏览(14)
  • ES6中let和const关键字与var关键字之间的区别?

    ES6中let和const关键字与var关键字之间的区别?

    前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供一个系统而又亲切的学习平台。在这个

    2024年02月09日
    浏览(13)
  • static,const,volatile,extern,register关键字深入解析

    static,const,volatile,extern,register关键字深入解析

    ✅作者简介:嵌入式入坑者,与大家一起加油,希望文章能够帮助各位!!!! 📃个人主页:@rivencode的个人主页 🔥系列专栏:玩转C语言 💬保持学习、保持热爱、认真分享、一起进步!! 我们都知道一个源文件要生成我们计算机课执行的文件要经过: 源文件(test.c)—预编

    2023年04月08日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包