c++关键字const

C++中的const是一种常量修饰符。在变量、函数参数和成员函数中使用const可以限制其对数据的修改。

const修饰的数据在定义时必须进行初始化,且不能被修改,因此使用const可以提高代码的安全性和可读性。C++中,const修饰的成员函数表示该函数保证不会修改类的成员变量,从而保证对象的状态不会被改变。使用const修饰的成员函数可以帮助程序员更好地实现不变类(不修改内部状态的类)和避免不必要的拷贝构造函数的调用。

C++中使用`const`的主要目的是为了告诉编译器某些变量或函数参数、类成员函数、关键字等不会被修改,从而提高代码的可读性、可维护性和安全性。使用`const`的主要注意事项如下:

1. 使用const修饰变量

使用const修饰变量时,需要注意以下几点:

- 定义时必须进行初始化,一旦初始化后,就不能再修改变量的值。

- const定义的常量存放在静态存储区,而不是栈中。

- 通常采用const全大写的命名方式来表示常量,提高可读性。

- 在函数参数列表中,const修饰的参数表明函数不能修改该参数的值。

2. 在类中使用const修饰成员变量

在类中使用const修饰成员变量时,需要注意以下几点:

- const成员变量必须在定义时进行初始化,在构造函数中无法进行初始化。

- const成员变量只能通过成员初始化列表进行初始化。

- 可以在构造函数中通过调用其他函数或者使用默认参数对const成员变量进行初始化。

- const成员变量的值不能在构造函数中被修改。

3. 在类中使用const修饰成员函数

在类中使用const修饰成员函数时,需要注意以下几点:

- const成员函数不能修改类的非静态成员变量。

- 如果类中有一个const成员函数,那么该成员函数是类的常量成员函数,只能被const对象调用,不能被非const对象调用。

- 具有相同名称和参数的另外一个非const成员函数可以修改类的成员变量。

使用const可以使你的代码更加安全、可读性更高,并且有助于防止一些不必要的错误。

为了避免const使用时出现的错误,需要在使用时注意以上细节,如常量的定义和初始化、使用const修饰的指针、const修饰的成员变量和成员函数、以及常量对象的初始化等细节。

// const修饰变量
#include <iostream>int main()
{// 定义并初始化Nconst int N = 10;// 使用const修饰变量N,使其成为一个常量。因为N是常量,所以可以用它定义数组并使用,但是在后面试图修改N的值是会编译错误。int arr[N];for (int i = 0; i < N; i++){arr[i] = i;std::cout << arr[i] << " ";}std::cout << std::endl;//const修饰的N不能修改, 编译报错,error: assignment of read-only variable ‘N’// N = 20;return 0;
}
// const修饰函数参数
#include <iostream>// const修饰函数参数
void arrPrint(const int arr[], const int size)
{for (int i = 0; i < size; i++){std::cout << arr[i]  << " ";}std::cout << std::endl;// const修饰的参数不能修改,编译报错试图对只读的数组元素进行赋值。error: assignment of read-only location ‘* arr’// arr[0] = 10;// size = 6;
}int main()
{int arr[5] = {1, 2, 3, 4, 5};int size = sizeof(arr) / sizeof(arr[0]);arrPrint(arr, size);return 0;
}
// const修饰成员函数
#include <iostream>class Circle {
public:// 常量数据成员通常不直接在声明时初始化赋值,不合适,一般使用成员初始化列表进行赋值Circle(double r) : radius(r) {}// const修饰成员函数double getArea() const {return 3.1415926 * radius * radius;}// const修饰成员函数double getRadius() const {// const修饰的radius不能修改,编译报错,error: assignment of member ‘Circle::radius’ in read-only object// radius = 3;return radius;}// const修饰数据成员const double radius;// 常量数据成员通常不直接在声明时初始化赋值,不合适,一般使用成员初始化列表进行赋值// const double radius = 5.0;
};int main()
{Circle c(5.0);std::cout << "radius : " << c.getRadius() << std::endl;std::cout << "area   : " << c.getArea() << std::endl;// const修饰的radius不能修改,编译报错,error: assignment of read-only member ‘Circle::radius’// c.radius = 3;return 0;
}
// const修饰的类枚举
#include <iostream>class Shape {
public:enum class Type : int {Circle = 0,Square = 1,};Shape(Type t) : type(t) {}void getType() const {switch (type){case Type::Circle:std::cout << "circle" << std::endl;break;case Type::Square :std::cout << "square" << std::endl;default:break;}}// const修饰的类枚举const Type type;
};int main()
{// 创建Shape对象,指定类型为CircleShape c(Shape::Type::Circle);c.getType();Shape s(Shape::Type::Square);s.getType();// const修饰的类枚举不能修改,编译错误,error: assignment of read-only member ‘Shape::type’// c.type = Shape::Type::Square;return 0;
}
// const修饰的静态类变量
#include <iostream>class Counter {
public:Counter() {count++;}Counter(const Counter & c) {count++;}static int getCount() {return count;}
private:// const修饰的静态成员变量static const int LIMIT = 10;// 类静态变量static int count;
};
// 定义静态成员变量
int Counter::count = 0;int main()
{Counter c1, c2, c3;std::cout << "count : " << Counter::getCount() << std::endl;// const修饰的类静态变量不能修改,编译错误,error: assignment of read-only variable ‘Counter::LIMIT’// Counter::LIMIT = 20;return 0;
}
// const修饰的非静态成员函数
#include <iostream>class Circle{
public:Circle(double r) : radius(r) {}double getArea() const {return PI * radius * radius;}double getRadius() const {return radius;}private:// 定义静态常量static const double PI;double radius;
};const double Circle::PI = 3.1415926;int main()
{const Circle c(5.0);std::cout << "area : " << c.getArea() << std::endl;return 0;
}
// const修饰的类转换函数
#include <iostream>class Point {
public:Point(int x, int y) : _x(x), _y(y) {}int getX() const {return _x;}int getY() const {return _y;}// 类中定义了一个使用const修饰的类转换函数:`operator int()`。// 该函数将一个Point对象转换为一个整数,这里我们将`_x`和`_y`简单地相加。// 在`main()`函数中,我们创建了一个`Point`对象,并将其转换为整数输出。// 由于在类转换函数中使用了const修饰,保证了不会修改对象operator int() const {return _x + _y;}
private:int _x;int _y;
};int main()
{Point p(3, 4);std::cout << static_cast<int>(p) << std::endl;return 0;
}
// const在函数前面修饰
// 在C++中,const可以用在函数的前面和后面,
// 用在函数后面是用来修饰成员函数,用在函数前面则是用来修饰函数返回值。它们的区别在于const的含义不同。
// const修饰成员函数和修饰函数返回值都能达到保护数据不被修改的目的,但用法和意义不同。必须根据实际情况选择适当的修饰。
// const在函数前面为常量函数,const在函数后面为常量成员函数
// 常量成员函数用于定义不能修改任何非静态成员数据的函数(或称“只读”函数),而常量函数用于定义不能修改其返回值的函数,使返回值更安全。
#include <iostream>class Rectangle {
public:Rectangle(int w, int h) : width(w), height(h) {}// const在函数后面用来修饰成员函数,表示该成员函数是一个常量成员函数,不能修改类的非静态成员变量。// 常量成员函数也不能被非const对象调用。int getArea() const;// 返回值类型为`const int &`,表示返回的是一个常量引用,不能修改它所引用的变量。// const在函数前面用来修饰函数返回值,表示该函数返回的值是一个常量。// 通常用于返回一个常量指针或常量引用,以避免返回值被修改。const int &max(const int &a, const int &b) {return (a > b) ? a : b;}// C++中`const`关键字可以用在函数返回值的前面或后面,// 用在函数返回类型前面就表示返回值是一个`const`常量,用在类型后面表示该函数是一个常量函数。// 所以`int const func()`和`const int func()`是等同的,它们都表示一个返回值是`const int`类型的函数。// 这种用法通常用于返回一个常量对象,或常量指针、常量引用等等,以避免返回值被修改。const int get100() {return 100;}int const get200() {// const修饰的是返回值,函数可以修改成员变量的值this->width = 200;return 200;}int getWidth() const {// 函数被声明为常量成员函数,因此不能修改成员变量的值// 不能修改成员变量,编译错误,error: assignment of member ‘Rectangle::m_val’ in read-only object// this->m_val = 100;return this->width;}void setValue(int value) {this->width = value;}// 当`const`关键字放在成员函数的前面时,它修饰的是函数的返回值,表示这个函数的返回值是一个常量。// 这种函数返回类型前加`const`关键字的写法,通常用于返回一个常量整数、常量指针或常量引用等,以避免返回值被修改。// 常量函数的常量限制作用于函数的返回值上,而非函数的实现代码中。// 函数的返回值类型被定义成`const int`,表明函数返回了一个常量整数const int getHeight() const {return this->height;}
private:int width, height;
};// 常成员函数,在函数尾部加const,常成员函数在类外实现的时候const不能丢掉,因为const时函数的一部分
// 在常成员函数中不能修改任何数据成员的值,常成员函数内不能对类的任何数据成员进行修改,
// 即当前类中凡是能用this指出来的成员都改不了,但是可以访问,就是只能看不能改,但是静态成员变量可以修改。
int Rectangle::getArea() const {// error: assignment of member ‘Rectangle::width’ in read-only object// width = 10;return width * height;
}int main()
{const Rectangle r(5, 10);std::cout << "area : " << r.getArea() << std::endl;// const放函数前面Rectangle r1(5, 10);// 常量引用`maxVal`来引用`max()`函数返回的值,因此不能修改`maxVal`的值。// 报错,error: passing ‘const Rectangle’ as ‘this’ argument discards qualifiers [-fpermissive]// const int & max = r.max(5, 10);const int & maxVal = r1.max(5, 10);// error: assignment of read-only reference ‘maxVal’// maxVal = 20;std::cout << "max val : " << maxVal << std::endl;// 报错,error: passing ‘const Rectangle’ as ‘this’ argument discards qualifiers [-fpermissive]// r.get100();const int a1 = r1.get100();// 报错,error: expected initializer before ‘a2’// 这个错误是因为`r1`对象是一个`const`对象,在`const`对象上调用非常量成员函数是不允许的,// 因为非常量成员函数可以修改对象的状态,会破坏对象的不可变性。// int cosnt a2 = r1.get100();std::cout << "get100  : " << r1.get100() << std::endl;std::cout << "get200  : " << r1.get200() << std::endl;// 创建了一个常量对象`obj`,也不能修改其中的成员变量。const Rectangle obj0(10, 20);std::cout << obj0.getWidth() << std::endl;// 不能修改常量对象的成员变量,编译错误,error: passing ‘const Rectangle’ as ‘this’ argument discards qualifiers [-fpermissive]// obj0.setValue(10);Rectangle obj1(10, 30);std::cout << obj1.getHeight() << std::endl;// 通过调用常量函数`obj.getValue()`来获取常量整数值,并将结果保存到一个常量值`value`中,这样可以防止常量值被修改。int a3 = obj1.getHeight();const int a4 = obj1.getHeight();std::cout << "a3 = " << a3 << ", a4 = " << a4 << std::endl;return 0;
}
// 常量成员函数和常量函数的区别
// - 常量成员函数在函数声明的结尾处加上`const`修饰符,用于定义不会修改任何非静态成员数据的函数。
// 也就是说,常量成员函数将其所操作的对象指定为常量,从而导致它不能在函数调用中修改类中的任何非静态成员变量。
// - 常量函数在函数返回类型前加上`const`修饰符,用于定义不能修改其返回值的函数。
// 也就是说,常量函数指定了函数返回的值是一个常量,无法被修改。
#include <iostream>class Rectangle {
public:Rectangle(int width, int height) : m_width(width), m_height(height) {}// 常量成员函数int getArea() const;int getValue() const;void setValue(int value);// 常量函数int const getWidth() const {return m_width;}const int getHeight() const {return m_height;}const int get100() {return m_height;}const int get200() {return m_height;}private:int m_width;int m_height;int m_value;
};// 常成员函数,在函数尾部加const,常成员函数在类外实现的时候const不能丢掉,因为const时函数的一部分
// 在常成员函数中不能修改任何数据成员的值,常成员函数内不能对类的任何数据成员进行修改,
// 即当前类中凡是能用this指出来的成员都改不了,但是可以访问,就是只能看不能改,但是静态成员变量可以修改。
int Rectangle::getArea() const {return m_width * m_height;
}int Rectangle::getValue() const {return m_value;
}void Rectangle::setValue(int value) {m_value = value;
}int main()
{// c++非常量对象可以调用类的常量成员函数,常量对象不能调用非常量成员函数const Rectangle r(3, 4);// 调用常量成员函数std::cout << "Area: " << r.getArea() << std::endl;// 调用常量函数const int value = r.getValue();std::cout << "Value: " << value << std::endl;// 不能在常量对象上调用非常量成员函数// r.setValue(5);  // 编译错误const Rectangle r1(10, 20);std::cout << "width : " << r1.getWidth() << ", height : " << r1.getHeight() << std::endl;// 常量对象不能调用非常量成员函数,报错,error: no matching function for call to ‘Rectangle::setValue() const’// r1.setValue();// r1.get100();// r1.get200();return 0;
}
// const常量对象
// C++中,如果对象被声明为常量对象,那么就意味着该对象的值不能被修改。
// 常量对象是指对象在创建后,其值被确定不变,不允许被修改。// 非常量对象可以调用常量成员函数,因为常量成员函数不会修改对象的状态,所以没有任何风险和限制。
// 而常量对象不能调用非常量成员函数,因为非常量成员函数有可能会修改对象的状态,这会与常量对象的定义相矛盾,所以编译器会拒绝这样的调用并报错。
#include <iostream>class Rectangle {
public:Rectangle(int width, int height) : m_width(width), m_height(height) {}int getArea() const;void setValue(int value);
private:int m_width;int m_height;
};// 常成员函数,在函数尾部加const,常成员函数在类外实现的时候const不能丢掉,因为const时函数的一部分
// 在常成员函数中不能修改任何数据成员的值,常成员函数内不能对类的任何数据成员进行修改,
// 即当前类中凡是能用this指出来的成员都改不了,但是可以访问,就是只能看不能改,但是静态成员变量可以修改。
int Rectangle::getArea() const {return m_width * m_height;
}void Rectangle::setValue(int value) {m_width = value;m_height = value;
}int main() {Rectangle r1(2, 3);  // 非常量对象// 在C++中,`const`关键字可以用在类型的右侧或左侧。// 当`const`关键字出现在类型名称的左侧时,它会作用于变量名之前的类型部分;// 当`const`关键字出现在类型名称的右侧时,它会作用于变量名之后的类型部分。// int const b = 20;  // 常量整数,等价于const int b = 20;// Rectangle const r3(5, 6);  // 常量对象,值不可修改,等价于const Rectangle r3(5, 6);const Rectangle r2(3, 4);  // 常量对象Rectangle const r3(5, 6);  // 常量对象r1.getArea();  // 非常量对象调用常量成员函数r2.getArea();  // 常量对象调用常量成员函数// r2.setValue(5);  // 编译错误,常量对象不能调用非常量成员函数r1.setValue(5);  // 非常量对象可以调用非常量成员函数return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/623316.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《计算思维导论》笔记:10.2 什么是数据库与数据库系统?

《大学计算机—计算思维导论》&#xff08;战德臣 哈尔滨工业大学&#xff09; 《10.2 什么是数据库与数据库系统&#xff1f;》 数据库 简单来讲&#xff0c;数据库就是相互有关联关系的数据的集合。 一个表聚集了具有相同结构类型的若干个对象一行数据反映了某一对象的相关…

Leetcode3002. 移除后集合的最多元素数

Every day a Leetcode 题目来源&#xff1a;3002. 移除后集合的最多元素数 解法1&#xff1a;贪心 可以将数组去重后分为三个部分&#xff1a;nums1 独有的&#xff0c;nums2 独有的&#xff0c;nums1 与 nums2 共有的。 求集合 S 时&#xff1a; 先选择两个数组独有的。…

(七)Java 分支结构 —— if...else、switch

目录 一. 前言 二. if 分支 2.1. if 语句 2.2. if...else 语句 2.3. if...else if...else 语句 2.4. 嵌套的 if…else 语句 三. switch 分支 四. 课后习题 一. 前言 Java 中的分支结构是程序控制流的重要组成部分&#xff0c;它们允许程序根据特定条件执行不同的代码块…

JVM:双亲委派机制类加载器

JVM&#xff1a;双亲委派机制 1. 例子2. 类加载器总结3. 类加载过程4. 双亲委派模型的执行流程&#xff1a;5. 双亲委派模型的好处 1. 例子 Java运行时环境有一个java.lang包&#xff0c;里面有一个ClassLoader类 我们自定义一个String类在java.lang包下&#xff0c;下面的…

C#编程-使用事件

使用事件 事件是一个动作或发生的事情,例如:鼠标点击、按键、鼠标移动或系统产生的通知。应用程序可以在事件发生的时候做出响应。通知的一个示例是中断。事件是对象发生的消息以表示事件的发生。事件是进程内通信的有效方法。它们对对象时有用的,因为它们标识了单个状态改…

YOLOv8改进 | Conv篇 | 利用YOLO-MS的MSBlock轻量化网络结构(既轻量又长点)

一、本文介绍 本文给大家带来的改进机制是利用YOLO-MS提出的一种针对于实时目标检测的MSBlock模块(其其实不能算是Conv但是其应该是一整个模块),我们将其用于C2f中组合出一种新的结构,来替换我们网络中的模块可以达到一种轻量化的作用,我将其用于我的数据集上实验,包括多个…

Leetcode 第 379 场周赛题解

Leetcode 第 379 场周赛题解 Leetcode 第 379 场周赛题解题目1&#xff1a;10035. 对角线最长的矩形的面积思路代码复杂度分析 题目2&#xff1a;10036. 捕获黑皇后需要的最少移动次数思路代码复杂度分析 题目3&#xff1a;10037. 移除后集合的最多元素数思路代码复杂度分析 题…

SpringBoot+SSM项目实战 苍穹外卖(11) Apache ECharts

继续上一节的内容&#xff0c;本节学习Apache ECharts&#xff0c;实现营业额统计、用户统计、订单统计和销量排名Top10功能。 数据统计效果图&#xff1a; 目录 Apache ECharts入门案例 营业额统计用户统计订单统计销量排名Top10 Apache ECharts Apache ECharts 是一款基于 …

Debezium发布历史67

原文地址&#xff1a; https://debezium.io/blog/2019/08/20/debezium-0-10-0-beta4-released/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. Debezium 0.10.0.Beta4 发布 八月 20, 2019 作者&#xff1a; Gun…

解锁 JavaScript 数组的强大功能:常用方法和属性详解(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

20240114总结:无聊周末or有聊周末

有时候&#xff0c;连着几个周末感觉好忙&#xff0c;比如要去体检、验光、复光、爬山、打球、参加婚礼、跨年、年终总结、、练习讲话、乙肝疫苗、正骨、按摩、西丽湖吃饭、每天三国一两个钟、看下电影啥的&#xff0c;很快&#xff0c;很碎片。 但是这个周末完全没任务&#…

Java中HashSet如何检查重复

HashSet是基于哈希表实现的无序的、不重复的集合类。它在添加元素时会自动检查是否存在重复元素&#xff0c;通过hashCode()和equals()方法来确定元素的相等性。 HashSet添加元素步骤&#xff0c;先通过hashCode找出位置&#xff0c;再通过equals()比较是否相等&#xff1a; …

毕业设计:基于python微博舆情分析系统+可视化+Django框架 K-means聚类算法(源码)✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…

C++ 完成Client分页显示log

分页显示t_log 1、获取用户的输入 1.1、写一个Input成员函数&#xff0c;处理输入进来的语句 std::string XClient::Input() {//清空缓冲//cin.ignore(4096, \n);string input "";for (;;){char a getchar();if (a < 0 || a \n || a \r)break;cout <<…

数据化思维:数据聚集与管理,数据运用与分析

数据化思维 数据化思维&#xff0c;是指在面对复杂问题时&#xff0c;通过收集、处理和分析数据&#xff0c;以数据为依据进行决策和解决问题的思维方式。它强调用事实说话&#xff0c;注重量化指标&#xff0c;能够帮助我们在海量信息中抽丝剥茧&#xff0c;发现深层次规律和…

LlamaIndex中的CustomLLM(在线加载模型)

一.使用 Flask 将模型封装为 REST 接口 主要是将 complete()和 stream_complete()方法封装为 REST 接口&#xff0c;如下所示&#xff1a; from flask import Flask, request, jsonify from transformers import AutoTokenizer, AutoModelForCausalLM app Flask(__name__)cla…

Linux comm命令教程:对比和分析文件内容(附案例详解和注意事项)

Linux comm命令介绍 comm&#xff0c;又称为_compare common lines_命令&#xff0c;是一个简易的Linux文件比较工具&#xff0c;主要用于标识出两个已排序文件中的共同部分。该命令逐行比较两个文件&#xff0c;并以三列形式显示结果。 Linux comm命令适用的Linux版本 通常…

Kubernetes 面试宝典

创建 Pod的主要流程? 客户端提交 Pod 的配置信息(可以是 yaml 文件定义的信息)到 kube-apiserver. Apiserver 收到指令后,通知 controllr-manager 创建一个资源对象 controller-manager 通过 apiserver 将 pod 的配置信息存储到 ETCD 数据中薪心中 kube-scheduler 检查到 p…

GPT编程:运行你的第一个聊天程序

环境搭建 很多机器学习框架和类库都是使用Python编写的&#xff0c;OpenAI提供的很多例子也是Python编写的&#xff0c;所以为了方便学习&#xff0c;我们这个教程也使用Python。 Python环境搭建 Python环境搭建有很多种方法&#xff0c;我们这里需要使用 Python 3.10 的环境…

一二三应用开发平台文件处理设计与实现系列之5——MinIO技术预研

背景 上篇介绍了文件读写框架设计与实现&#xff0c;同时顺便说明了本地磁盘存储模式的实现模式。 今天来说下基于文件读写框架&#xff0c;如何集成对象存储组件minio&#xff0c;集成之前&#xff0c;需要对minio进行必要的了解&#xff0c;本篇是minio的技术预研。 minio简…