20.介绍一下const

2026-01-23
2109 字 · 11 分钟

🔬 介绍一下const

📖 内容概览

const是C++中最重要的关键字之一,它用于定义不可修改的常量和约束对象的访问权限。const可以应用于变量、指针、引用、函数参数、函数返回值和成员函数等多种场景,能够显著提高程序的安全性、可靠性和可读性。本文将详细解析const的各种用法、特性、最佳实践以及与其他相关概念的区别。

🎯 核心概念

🧩 const的基本定义

const是一个类型修饰符,用于限定一个对象或表达式的值不可被修改。它可以应用于几乎所有的C++类型,包括基本类型、复合类型、自定义类型等。

📋 const的主要作用

  • 提高安全性:防止意外修改数据
  • 增强可读性:明确标识不可修改的数据
  • 优化性能:允许编译器进行更多优化
  • 支持函数重载:const成员函数可以与非const成员函数重载
  • 支持常量表达式:在编译期计算值

🛠️ 代码示例

🔧 const修饰变量

// 基本类型常量
const int MAX_SIZE = 100;
const double PI = 3.1415926;
// 数组常量
const int ARRAY[] = {1, 2, 3, 4, 5};
const size_t ARRAY_SIZE = sizeof(ARRAY) / sizeof(ARRAY[0]);
// 自定义类型常量
class Person {
public:
Person(const std::string& name, int age)
: name_(name), age_(age) {}
std::string getName() const { return name_; }
int getAge() const { return age_; }
private:
const std::string name_; // 成员变量常量
int age_;
};
const Person PERSON("Alice", 30);

2. const修饰指针

int a = 10;
int b = 20;
// 常量指针:指向常量的指针(不能通过指针修改指向的值)
const int* p1 = &a;
// *p1 = 30; // ❌ 错误:不能修改指向的值
p1 = &b; // ✅ 可以改变指针指向
// 指针常量:指针本身是常量(不能改变指针指向)
int* const p2 = &a;
*p2 = 30; // ✅ 可以修改指向的值
// p2 = &b; // ❌ 错误:不能改变指针指向
// 常量指针常量:既不能改变指针指向,也不能修改指向的值
const int* const p3 = &a;
// *p3 = 30; // ❌ 错误:不能修改指向的值
// p3 = &b; // ❌ 错误:不能改变指针指向

3. const修饰引用

int x = 10;
const int& ref = x; // 常量引用
// ref = 20; // ❌ 错误:不能修改引用的值
x = 20; // ✅ 可以通过原变量修改值
// 常量引用可以绑定到临时对象
const int& temp_ref = 42; // ✅ 正确
// int& temp_ref2 = 42; // ❌ 错误:非常量引用不能绑定到临时对象

4. const修饰函数参数

#include <iostream>
#include <string>
// 防止函数内部修改参数
void printArray(const int* arr, size_t size) {
for (size_t i = 0; i < size; ++i) {
// arr[i] = 0; // ❌ 错误:不能修改const参数
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
// 提高传递效率(避免拷贝大对象)
void processString(const std::string& str) {
// 可以读取str,但不能修改
std::cout << "String length: " << str.length() << std::endl;
}

5. const修饰函数返回值

// 返回const值,防止结果被修改
const int getMax(const int a, const int b) {
return a > b ? a : b;
}
// 返回const引用,避免拷贝,同时防止修改
class MyClass {
int data_;
public:
MyClass(int data) : data_(data) {}
const int& getData() const { return data_; }
};

6. const修饰成员函数

class Circle {
double radius_;
public:
Circle(double radius) : radius_(radius) {}
// const成员函数:不能修改对象的成员变量
double getArea() const {
// radius_ = 10; // ❌ 错误:不能修改成员变量
return 3.14159 * radius_ * radius_;
}
// 非const成员函数:可以修改对象的成员变量
void setRadius(double radius) {
radius_ = radius;
}
};
// const对象只能调用const成员函数
const Circle const_circle(5.0);
const_circle.getArea(); // ✅ 可以调用const成员函数
// const_circle.setRadius(10.0); // ❌ 错误:不能调用非const成员函数
// 非const对象可以调用const和非const成员函数
Circle circle(5.0);
circle.getArea(); // ✅ 可以调用const成员函数
circle.setRadius(10.0); // ✅ 可以调用非const成员函数

🔍 const的高级用法

const与typedef

// 注意:const修饰的是整个类型
typedef int* IntPtr;
const IntPtr p; // 等价于 int* const p(指针常量)
// 而不是 const int* p(常量指针)
// 推荐使用using声明,更清晰
using IntPtr = int*;
const IntPtr p2; // 同样等价于 int* const p2

const与volatile

const和volatile可以同时使用,表示一个值不可修改但可能被外部因素改变(如硬件寄存器):

// const volatile指针:指向常量的volatile指针
const volatile int* hardware_register = (const volatile int*)0x1234;

const与constexpr

特性constconstexpr
计算时机编译期或运行期必须编译期
应用范围变量、指针、引用、函数等变量、函数、构造函数等
优化程度中等更高
数组大小C++11后可以可以
类成员可以可以
// 函数声明,用于演示
int getSize();
const int size1 = 10; // 编译期常量
const int size2 = getSize(); // 运行期常量
constexpr int size3 = 10; // 编译期常量
// constexpr int size4 = getSize(); // ❌ 错误:getSize()不是编译期可计算的
constexpr int add(int a, int b) {
return a + b;
}
constexpr int sum = add(3, 4); // 编译期计算,sum=7

⚠️ 注意事项

1. const与宏定义的区别

特性const#define
类型检查
作用域遵循C++作用域规则全局,直到#undef
调试信息
内存分配编译期优化,可能不分配简单文本替换,无内存分配
安全性
推荐:使用const代替宏定义,除非需要文本替换功能。

2. const对象的初始化

const int x; // ❌ 错误:const变量必须初始化
const int y = 10; // ✅ 正确:初始化
// 类的const成员必须在构造函数初始化列表中初始化
class MyClass {
private:
const int value_;
public:
MyClass(int value) : value_(value) {} // ✅ 正确:初始化列表
// MyClass(int value) { value_ = value; } // ❌ 错误:赋值操作
};

3. const与引用传递

推荐:对于大对象,优先使用const T&传递参数,避免拷贝开销: // 不推荐:拷贝大对象,效率低 void processBigObject(BigObject obj); // 推荐:传递const引用,避免拷贝 void processBigObject(const BigObject& obj);

4. const与函数重载

const成员函数可以与非const成员函数重载,编译器会根据对象是否为const来选择调用哪个版本: class String { char& operator[](size_t index) { return data_[index]; // 非const版本:允许修改 }

const char& operator[](size_t index) const {
return data_[index]; // const版本:不允许修改
char data_[100];

String str = “Hello”; const String const_str = “World”; str[0] = ‘h’; // 调用非const版本,允许修改 const_str[0] = ‘w’; // ❌ 错误:const对象调用const版本,不允许修改

🛠️ 最佳实践

  1. 尽可能使用const:只要对象不需要修改,就声明为const
  2. 优先使用const引用传递参数:对于大对象,避免拷贝开销
  3. 使用const成员函数:不修改对象状态的成员函数都应声明为const
  4. 使用constexpr代替const:对于编译期可计算的值,优先使用constexpr
  5. 避免const_cast:除非万不得已,不要使用const_cast移除const属性
  6. 使用const迭代器:遍历容器时,如果不需要修改元素,使用const迭代器
  7. 声明返回值为const:如果函数返回值不需要被修改,声明为const

📋 总结

const是C++中最强大的关键字之一,它提供了多种方式来约束对象的访问权限和修改权限。通过合理使用const,可以显著提高程序的安全性、可靠性和可读性,同时允许编译器进行更多优化。

const的主要用法

  • const变量:定义不可修改的常量
  • const指针:控制指针的指向和指向对象的修改权限
  • const引用:安全地传递大对象,避免拷贝
  • const参数:防止函数内部修改参数
  • const返回值:防止返回值被意外修改
  • const成员函数:不能修改对象的成员变量

const的核心优势

  • 安全性:防止意外修改数据
  • 可读性:明确标识不可修改的数据
  • 性能:允许编译器进行更多优化
  • 灵活性:支持多种使用场景和约束级别 理解和掌握const的各种用法是成为优秀C++程序员的必备技能之一,建议在实际开发中养成广泛使用const的习惯。

Thanks for reading!

20.介绍一下const

2026-01-23
2109 字 · 11 分钟

已复制链接

评论区

目录