热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++中const修饰符的详解及其作用介绍_C语言

这篇文章主要介绍了C++中const修饰符的详解及其作用介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,

概述

const 是 constant 的缩写, 是不变的意思. 在 C++ 中是用来修饰内置类型变量, 自定义对象, 成员函数, 返回值, 函数参数. const 可以帮我们避免无意之中的错误操作.

在这里插入图片描述

使用 const, 把有关的数据定义为常量 (常变量 / 常对象 / 常函数). const 既可以使数据在一定范围内共享, 又要保证它不被任意修改.

const 包括:

  • 常对象
  • 常指针
  • 常引用

常对象

我们可以将需要保证数据成员不改变的对象, 可以声明为常对象. 常对象中的所有成员的值都不能被修改.

常变量的两种格式:

类名 const 对象名[(实参表列)];
const 类名 对象名[(实参表列)];

常对象必须要有初始值. 例如:

Time const t1(12, 34, 46);
const Time t1(12, 34, 46);

试图改变常对象的成员值会发生什么:

int main() {

    const Time t1(10, 10, 10);  // 定义const Time对象
    t1.set_time(2,2,2);  // 试图改变t1对象的成员数据, 报错

    return 0;
}

输出:
C:\Users\Windows\CLionProjects\Project1\main.cpp: In function 'int main()':
C:\Users\Windows\CLionProjects\Project1\main.cpp:10:22: error: passing 'const Time' as 'this' argument discards qualifiers [-fpermissive]
     t1.set_time(2,2,2);
                      ^
In file included from C:\Users\Windows\CLionProjects\Project1\main.cpp:2:
C:\Users\Windows\CLionProjects\Project1\Time.h:12:10: note:   in call to 'void Time::set_time(int, int, int)'
     void set_time(int h, int m=0, int s=0);
          ^~~~~~~~
mingw32-make.exe[3]: *** [CMakeFiles\Project1.dir\build.make:81: CMakeFiles/Project1.dir/main.cpp.obj] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:94: CMakeFiles/Project1.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:101: CMakeFiles/Project1.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:136: Project1] Error 2

常对象成员

常成员函数

如果我们要引用常对象中的数据成员, 就需要将该成员函数声明为 const 型函数, 即常成员函数. 常成员函数可以访问对象中的数据成员, 但不允许修改常对象中数据成员的值.

举个栗子:

Time 类:

#ifndef PROJECT1_TIME_H
#define PROJECT1_TIME_H

class Time {
private:
    int minute;
    int second;
public:
    int hour;
    Time();  // 默认构造函数
    Time(int h, int m=0, int s=0);  // 有参构造函数
    void set_time(int h, int m=0, int s=0);
    void show_time() const;  // 声明为常成员函数
};

#endif //PROJECT1_TIME_H

Time.cpp:

#include "Time.h"
#include 
using namespace std;

// 默认构造函数
Time::Time() : hour(0), minute(0), second(0) {}

// 有参构造函数
Time::Time(int h, int m, int s) : hour(h), minute(m), second(s) {}

void Time::set_time(int h, int m, int s) {
    hour = h;
    minute = m;
    secOnd= s;
}

void Time::show_time() const {
    cout <

main:

#include "Time.h"
#include 
using namespace std;

int main() {

    const Time t1(10, 10, 10);  // 定义const Time对象
    t1.show_time();  // 调用常成员函数

    return 0;
}

调试输出:

10:10:10

注: const 是函数类型的一部分, 在声明函数和定义函数时都要有 const 关键字.

常数据成员

当我们用关键字 const 来声明常量数据成员, 可以限定其值不能改变.

Time 类:

#ifndef PROJECT1_TIME_H
#define PROJECT1_TIME_H

class Time {
private:

public:
    const int hour;  // 定义hour为常数据成员
    int minute;
    int second;

    Time();  // 默认构造函数
    Time(int h, int m=0, int s=0);  // 有参构造函数
    void set_time(int m=0, int s=0);
    void show_time() const;  // 声明为常成员函数
};

#endif //PROJECT1_TIME_H

因为 hour 为常数据成员, 所以我们只能通过构造函数的参数初始化表对常数据成员进行初始化.

// 默认构造函数
Time::Time() : hour(0), minute(0), second(0) {}

// 有参构造函数
Time::Time(int h, int m, int s) : hour(h), minute(m), second(s) {}

我们不能再构造函数中用赋值的方法对常数据成员初始化. 例如:

Time::Time(int h){hour=h;}  // 非法

不能用成员函数改变常数据成员的值. 例如:

void Time::setHour(int h){hour=h;}  // 非法

数据成员访问限制

常对象中的成员函数未加 const, 编译系统认为其是非 const 成员函数.

在这里插入图片描述

常对象修改的限制

如果一个对象被声明为常对象, 则不能调用该对象的非 const 型的成员函数, 除了由系统自动调用的隐式的构造函数和析构函数.

要点:

  • 编辑系统只检查函数的声明, 只要发现调用了常对象的成员函数, 而该函数未被声明为 const, 就报错
  • 防止函数修改常对象中数据成员的值
  • 编译系统对不安全的因素予以拦截, 为我们开发人员省了不少心
  • 用常成员函数引用常变量

常指针

将指针变量声明为 const 型, 指针值始终保持为其初始值, 不能改变.

指向对象的常指针格式:

类名 *const 变量名;
Time time1(10, 12, 15), t2;
Time * const pt = &t1  // pt 是常指针
pt = &t2; // 将一个指针固定

常见用途: 将一个指针固定地与一个对象联系. 将常指针作为函数的形参, 目的是不允许在函数执行过程中改变指针变量的值.

void doSomething(Test * const p1){
    p1 -> setX(5);
    p1 -> printxy();
} 

指向常变量的指针

定义指向常变量的指针变量的一般形式为:

const 类名 *变量名 / 类型名 const *变量名;

只有常变量的指针能指向常变量:

在这里插入图片描述

指向常变量的指针变量可以指向未被声明为 const 的变量, 但不能通过此指针变量改变该变量的值.

在这里插入图片描述

重点:

  • 如果一个变量已被声明为常变量 / 对象. 我们就只能用指向常变量的指针指向他, 而不能用非 const 型的变量 / 对象的指针去指向它.

指向对象的指针

定义指向对象的指针变量的一般形式为.

const 类名 *变量名 / 类名 const *变量名;

举个栗子:

在这里插入图片描述

如果一个对象已经被声明为常对象, 我们就只能用指向常对象的指针指向他. 而不能用指向非 const 型变量 / 对象的指针指向他.

指向常对象的指针变量可以指向未被声明为 const 的对象, 但不能通过此指针来改变该对象的值. 例如:

在这里插入图片描述

小结

指向常对象的指针最常用语函数的形参, 以保护形参指针所指向的对象在函数执行过程中不被修改.

当我们希望在调用函数时对象的值不被修改, 就应当把形参定义为指向常对象的指针变量. 同时用对象的地址作为实参 (对象可以是 const 或非 const 型).

在这里插入图片描述

在这里插入图片描述

对象的常引用

一个变量的应用就是变量的别名. 变量名和引用名都指向同一段没存单元.

函数的形参可以是对象的引用. 如果不希望在函数中修改实参的值, 可以将形参声明为常引用. 例如:

void fun(Time &t); 
void fun(const Time &);  // 常引用

我们应该尽量使用常引用作为函数参数, 原因有二:

  1. 既能保证数据安全, 使数据不能被随意修改
  2. 在调用函数时不必建立实参的copy, 可以提高程序运行效率

总结

在这里插入图片描述


推荐阅读
  • BZOJ1034 详细解析与算法优化
    本文深入解析了BZOJ1034问题,并提出了优化算法。通过借鉴广义田忌赛马的贪心策略,当己方当前最弱的马优于对方最弱的马时进行匹配;同样地,若己方当前最强的马优于对方最强的马,也进行匹配。此方法在保证胜率的同时,有效提升了算法效率。 ... [详细]
  • BZOJ4240 Gym 102082G:贪心算法与树状数组的综合应用
    BZOJ4240 Gym 102082G 题目 "有趣的家庭菜园" 结合了贪心算法和树状数组的应用,旨在解决在有限时间和内存限制下高效处理复杂数据结构的问题。通过巧妙地运用贪心策略和树状数组,该题目能够在 10 秒的时间限制和 256MB 的内存限制内,有效处理大量输入数据,实现高性能的解决方案。提交次数为 756 次,成功解决次数为 349 次,体现了该题目的挑战性和实际应用价值。 ... [详细]
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • 在处理UVA11987问题时,关键在于实现并查集结构以支持删除操作。特别地,当需要删除某个节点时,如果该节点不是根节点,则处理相对简单;然而,若删除的是根节点,则需要进行额外的处理来维护集合的连通性。本文将详细介绍如何通过优化并查集算法,确保在删除根节点时仍能高效地维护数据结构的完整性和查询效率。 ... [详细]
  • Prim算法在处理稠密图时表现出色,尤其适用于边数远多于顶点数的情形。传统实现的时间复杂度为 \(O(n^2)\),但通过引入优先队列进行优化,可以在点数为 \(m\)、边数为 \(n\) 的情况下显著降低时间复杂度,提高算法效率。这种优化方法不仅能够加速最小生成树的构建过程,还能在大规模数据集上保持良好的性能表现。 ... [详细]
  • 计算 n 叉树中各节点子树的叶节点数量分析 ... [详细]
  • 在进行网络编程时,准确获取本地主机的IP地址是一项基本但重要的任务。Winsock作为20世纪90年代初由Microsoft与多家公司共同制定的Windows平台网络编程接口,为开发者提供了一套高效且易用的工具。通过Winsock,开发者可以轻松实现网络通信功能,并准确获取本地主机的IP地址,从而确保应用程序在网络环境中的稳定运行。此外,了解Winsock的工作原理及其API函数的使用方法,有助于提高开发效率和代码质量。 ... [详细]
  • 本文作为“实现简易版Spring系列”的第五篇,继前文深入探讨了Spring框架的核心技术之一——控制反转(IoC)之后,将重点转向另一个关键技术——面向切面编程(AOP)。对于使用Spring框架进行开发的开发者来说,AOP是一个不可或缺的概念。了解AOP的背景及其基本原理,对于掌握这一技术至关重要。本文将通过具体示例,详细解析AOP的实现机制,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法
    结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法 ... [详细]
  • C++ 进阶:类的内存布局与虚函数类的实现细节
    C++ 进阶:类的内存布局与虚函数类的实现细节 ... [详细]
  • 本文详细探讨了C语言中`extern`关键字的简易编译方法,并深入解析了预编译、`static`和`extern`的综合应用。通过具体的代码示例,介绍了如何在不同的文件之间共享变量和函数声明,以及这些关键字在编译过程中的作用和影响。文章还讨论了预编译过程中宏定义的使用,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 本文详细介绍了如何在Linux系统中搭建51单片机的开发与编程环境,重点讲解了使用Makefile进行项目管理的方法。首先,文章指导读者安装SDCC(Small Device C Compiler),这是一个专为小型设备设计的C语言编译器,适合用于51单片机的开发。随后,通过具体的实例演示了如何配置Makefile文件,以实现代码的自动化编译与链接过程,从而提高开发效率。此外,还提供了常见问题的解决方案及优化建议,帮助开发者快速上手并解决实际开发中可能遇到的技术难题。 ... [详细]
  • 求助高手:下载的压缩包中包含CMake文件,如何在Windows环境下使用已安装的CMake GUI进行运行?
    从GitHub仓库 `https://github.com/vonmax007/RobotSimulation` 下载的代码包含多种算法,其中算法1的文件目录中包含了CMake文件。为了在Windows环境下使用已安装的CMake GUI运行这些文件,需要先确保CMake已正确安装,并按照以下步骤操作:打开CMake GUI,设置源代码路径和构建路径,点击“Configure”配置项目,然后点击“Generate”生成构建文件。最后,在生成的构建目录中使用命令行或IDE进行编译和运行。 ... [详细]
  • 本文介绍了一种使用C语言实现三角形绘制的方法。通过在主函数中调用多个`printf`语句,分别输出不同数量的星号,从而构建出一个简单的直角三角形。该方法简单直观,适用于初学者理解和掌握基本的C语言输出操作。此外,还可以通过调整`printf`语句中的星号数量和行数,来绘制不同大小和形状的三角形。 ... [详细]
author-avatar
幸福树袋熊2502903015
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有