当前位置: 首页 > news >正文

c++ const 关键字

const 关键字:
它是 C++ 中用于定义常量、确保程序正确性和安全性的最重要关键字之一。

1. const 的核心思想:不变性

const 的基本含义是“常量”或“只读”。它用于告诉编译器和程序员:这个对象或数据在初始化后,其值不能再被修改。任何试图修改 const 值的操作都会导致编译错误。

这带来了两大好处:

  1. 安全性:防止意外修改不该修改的数据。

  2. 可读性与可维护性:明确表达了设计意图(“这个值不会变”),使代码更易于理解。


2. const 的主要用法

1. 定义常量变量

这是最基础的用法,用于取代 C 语言中的 #define 宏常量。

cpp

const int MAX_BUFFER_SIZE = 1024;
const double PI = 3.1415926535;
const std::string GREETING = "Hello, World!";// MAX_BUFFER_SIZE = 2048; // 错误:不能给常量赋值

优势 over #define

  • 有类型检查,更安全。

  • 遵守作用域规则(如命名空间、类作用域)。

  • 可以通过调试器看到符号名。

2. 指针与 const

指针的 const 用法比较复杂,有两种形式,取决于 const 相对于 * 的位置:

  • 指向常量的指针 (Pointer to const):指针指向的内容是常量,不能通过该指针修改内容,但指针本身可以指向别的地址。

    cpp

  • int value = 10;
    const int* ptr = &value; // 或者 int const* ptr
    // *ptr = 20;           // 错误:不能通过 ptr 修改 value
    value = 20;             // 正确:value 本身不是常量,可以直接修改
    ptr = nullptr;          // 正确:指针本身可以改变
  • 常量指针 (Const pointer):指针本身是常量,初始化后不能再指向其他地址,但可以通过它修改所指的内容(除非内容也是常量)。

    cpp

  • int value1 = 10, value2 = 20;
    int* const ptr = &value1;
    *ptr = 15;              // 正确:可以修改所指的内容
    // ptr = &value2;       // 错误:指针本身是常量,不能改变指向
  • 指向常量的常量指针 (Const pointer to const):指针本身和所指的内容都是常量。

    cpp

  • int value = 10;
    const int* const ptr = &value;
    // *ptr = 20;   // 错误:不能修改所指内容
    // ptr = nullptr; // 错误:不能修改指针本身

记忆口诀

const* 左边指向的内容是常量 (const int*)。
const* 右边指针本身是常量 (int* const)。

3. 函数与 const
  • const 形参:防止函数内部修改传入的参数。常用于传递大型对象(如 const std::string&),既避免拷贝又保证原对象不被修改。

    cpp

  • void printMessage(const std::string& msg) {std::cout << msg << std::endl;// msg.clear(); // 错误:msg 是 const 引用,不能修改
    }
  • const 成员函数:这是 const 在类中极其重要的用法。它被放在成员函数声明的末尾

    cpp

class MyClass {
private:int m_value;mutable int m_counter; // mutable 成员即使在 const 函数中也能被修改
public:int getValue() const { // 这是一个 const 成员函数// m_value = 100; // 错误:不能修改类的非 mutable 成员变量m_counter++;      // 正确:m_counter 是 mutable 的return m_value;}void setValue(int val) { // 这是一个非 const 成员函数m_value = val;       // 可以修改成员变量}
};

const 成员函数的意义

  • 它向编译器承诺:这个函数不会修改调用它的对象的状态(除了 mutable 成员)。

  • 它允许const 对象调用

cpp

  • const MyClass obj1;
    // obj1.setValue(5); // 错误:const 对象不能调用非 const 成员函数
    int x = obj1.getValue(); // 正确:const 对象可以调用 const 成员函数MyClass obj2;
    obj2.getValue(); // 正确:非 const 对象也可以调用 const 成员函数
  • const 返回值:表示函数返回的值是常量,不能被修改。较少使用,但有时可以防止误操作。

    cpp

  • const int* getPointer() {static int value = 42;return &value;
    }
    // *(getPointer()) = 100; // 错误:返回值是 const int*
4. const 与引用
  • 常量引用 (const T&):这是 C++ 中最常用的传递参数的方式之一,尤其是对于自定义类型。

    cpp

void processBigObject(const VeryLargeObject& obj) {// 可以读取 obj,但不能修改它// 避免了拷贝大型对象的开销,又保证了安全性
}

常量引用有一个重要特性:它可以绑定到右值(临时对象)

cpp

  • void func(const std::string& str);
    func("hello"); // 正确:常量引用可以绑定到临时字符串
5. constexpr (C++11 引入)

constexprconst 的增强版,它表示“常量表达式”。不仅值不可变,而且必须在编译期就能计算出结果

cpp

constexpr int square(int x) { return x * x; }
constexpr int max_size = square(10); // 编译期计算int arr[max_size]; // 可以用作数组大小(因为编译期可知)

constexprconst 要求更严格,但能提供更好的性能(编译期计算)和更广的用途(如模板元编程)。


3. const 的威力:重载

const 可以用于函数重载。编译器会根据调用对象的常量性来选择调用哪个版本。

cpp

class MyArray {
public:int& operator[](size_t index) { // 用于非 const 对象,返回引用可修改return m_data[index];}const int& operator[](size_t index) const { // 用于 const 对象,返回 const 引用return m_data[index];}
private:int m_data[10];
};int main() {MyArray arr1;const MyArray arr2;arr1[0] = 100;  // 调用非 const 版本int a = arr2[0]; // 调用 const 版本// arr2[0] = 200; // 错误:调用的是 const 版本,返回不可修改的引用
}

4. 类型安全:const_cast 与去除常量性

虽然 const 表示不可修改,但 C++ 提供了 const_cast 运算符来移除 const 限定符。这是一项非常危险的操作,必须极其谨慎地使用

它主要用于与旧的、没有正确使用 const 的 C 语言库接口进行交互。

cpp

void oldCLibraryFunction(char* str) { // 一个不修改 str 的C函数,但参数没声明为const// ...
}int main() {const char* my_str = "Hello";// oldCLibraryFunction(my_str); // 错误:不能将 const char* 转换为 char*oldCLibraryFunction(const_cast<char*>(my_str)); // 强制转换,语法上通过了// 但如果 oldCLibraryFunction 真的修改了 my_str 指向的内容...// ...程序将导致未定义行为(UB),因为试图修改常量区的字符串字面量!
}

规则:只有在你绝对确定一个对象原本就不是 const,只是通过 const 指针或引用来访问它时,才能使用 const_cast


总结与实践建议

用法描述好处
const 变量定义运行期常量替代宏,类型安全,有作用域
const 参数函数不会修改的输入参数防止意外修改,常与引用合用避免拷贝
const 成员函数不修改对象状态的成员函数const 对象可用,明确接口契约
const 返回值返回不可修改的值防止客户端误修改
const 引用只读别名高效传递对象,可绑定临时对象
constexpr编译期常量性能优化,可用于更多场景(如数组大小)

最佳实践

  1. 默认使用 const:在定义变量、参数、引用和成员函数时,只要不需要修改,就加上 const。这是一种良好的防御性编程习惯。

  2. 按需使用 const:对于内置类型的小型参数,传值往往比传 const 引用更高效。

  3. 正确使用 const 成员函数:为所有不修改对象状态的 getter 函数加上 const

  4. 避免使用 const_cast:除非是在与劣质库接口的不得已情况下。

  5. 优先考虑 constexpr:如果需要在编译期确定值,使用 constexpr

http://www.dtcms.com/a/357035.html

相关文章:

  • 聊聊Prompt Engineering (提示词工程)
  • 【工具类】得到多个数组中的相同元素
  • 考研数据结构Part3——二叉树知识点总结
  • Vue学习Ⅳ
  • 二手车估值查询-二手车估值api接口
  • el-table实现双击编辑-el-select选择框+输入框限制非负两位小数
  • HunyuanVideo-Foley视频音效生成模型介绍与部署
  • 非标设计 机架模板 misumi 设计组合案例
  • 浏览器自动化工具怎么选?MCP 控制浏览器 vs Selenium 深度对比
  • 预测模型及超参数:3.集成学习:[1]LightGBM
  • LangChain实战(三):深入理解Model I/O - Prompts模板
  • 顶会顶刊图像分类的云服务器训练方法
  • 闭包与内存泄漏:深度解析与应对策略
  • Spring boot 启用第二数据源
  • Java全栈工程师的实战面试:从基础到微服务架构
  • 【SOD】目标检测
  • 2025.8.29机械臂实战项目
  • 基于STM32单片机的智能温室控制声光报警系统设计
  • leetcode 461 汉明距离
  • 基于MSRDCN、FEAM与AMSFM的轴承故障诊断MATLAB实现
  • 【工具】开源大屏设计器 自用整理
  • golang接口详细解释
  • websocket的应用
  • 【Spring Cloud Alibaba】前置知识
  • 微信小程序调用蓝牙打印机教程(TSPL命令)
  • Android 14 PMS源码分析
  • Linux-搭建DNS服务器
  • 计算机三级嵌入式填空题——真题库(24)原题附答案速记
  • CMake xcode编译器属性设置技巧
  • JavaScript 数组核心操作实战:最值获取与排序实现(从基础到优化)