C++ const 用法全面总结与深度解析
取const变量地址时const变量为非整数类型(如double、字符串)使用extern声明的const变量。
-
取const变量地址时
-
const变量为非整数类型(如double、字符串)
-
使用extern声明的const变量
const与#define的关键区别:
| 特性 | const | #define |
|---|---|---|
| 类型检查 | 有完整类型检查 | 无类型检查,仅文本替换 |
| 作用域 | 遵循块作用域规则 | 从定义处到文件结束 |
| 内存分配 | 通常不分配(除非取地址) | 不分配,仅预处理替换 |
| 调试支持 | 可被调试器识别 | 调试器中不可见 |
1.2 基本语法与初始化要求
代码语言:C++
自动换行
AI代码解释
const int MAX_SIZE = 100; // 正确:编译期常量,必须初始化
const double PI; // 错误:const变量必须初始化
int x = 5;
const int SIZE = x; // 正确:C++11起支持运行时常量
注意:全局const变量默认具有内部链接(仅当前文件可见),如需多文件共享,需显式声明为
extern const int MAX_SIZE = 100;
2. const 的各种用法深度解析
2.1 常量变量
功能详解:
-
const变量一旦初始化,其值在生命周期内不可修改
-
局部const变量存储在栈区,全局const变量通常存储在只读数据段(.rodata)
-
基本类型的const变量可用于数组大小(C++11起)
常见问题与坑点:
展开
代码语言:C++
自动换行
AI代码解释
const int x = 10;
int* px = (int*)&x; // 危险:通过强制类型转换绕过const检查
*px = 20; // 未定义行为!可能导致程序崩溃或异常结果
// 正确用法示例
const int BUFFER_SIZE = 256;
char buffer[BUFFER_SIZE]; // 正确:编译期常量可用于数组大小
2.2 const 与指针
2.2.1 三种const指针类型对比
| 类型 | 语法 | 指针本身 | 指向内容 | 记忆口诀 |
|---|---|---|---|---|
| 指向常量的指针 | const int* ptr |
可修改 | 不可修改 | 左定值(const在*左,值不可变) |
| 常量指针 | int* const ptr |
不可修改 | 可修改 | 右定向(const在*右,指针不可变) |
| 指向常量的常量指针 | const int* const ptr |
不可修改 | 不可修改 | 左右定值定向 |
2.2.2 指针转换规则
展开
代码语言:C++
自动换行
AI代码解释
int a = 10, b = 20;
const int* p1 = &a; // 正确:非const -> const(安全转换)
int* p2 = p1; // 错误:const -> 非const(危险,需显式转换)
int* p3 = const_cast<int*>(p1); // 允许但危险
int* const p4 = &a;
p4 = &b; // 错误:常量指针不可修改指向
// 实际应用场景:函数参数保护
void printData(const int* data, int size) {
// data[0] = 5; // 错误:保护数据不被修改
for(int i=0; i<size; i++) cout << data[i];
}
最佳实践:函数参数优先使用
const T*而非T*,除非确实需要修改指针指向的数据
2.3 const 与函数参数
2.3.1 三种参数传递方式对比
| 传递方式 | 语法 | 适用场景 | 优势 |
|---|---|---|---|
| 值传递 | void func(const int x) |
基本类型小数据 | 调用者无需担心数据被修改 |
| 指针传递 | void func(const T* ptr) |
大对象,需传递nullptr | 避免拷贝,保护指向内容 |
| 引用传递 | void func(const T& ref) |
大对象,无需传递nullptr | 避免拷贝和指针语法,保护对象 |
2.3.2 const引用的特殊特性
const引用可以绑定到临时对象,并延长其生命周期:
展开
代码语言:C++
自动换行
AI代码解释
#include <string>
std::string getString() { return "temporary string"; }
void processString(const std::string& str) {
// str生命周期被延长至函数结束
std::cout << str.length();
}
int main() {
processString(getString()); // 正确:临时对象绑定到const引用
// std::string& str = getString(); // 错误:非const引用不能绑定临时对象
return 0;
}
常见问题:
展开
代码语言:C++
自动换行
AI代码解释
void func(const int& x) {
// x = 5; // 错误:不能修改const引用
}
int main() {
int a = 10;
const int& ref = a;
a = 20;
std::cout << ref; // 输出20:const引用跟踪原变量变化
return 0;
}
2.4 const 与函数返回值
2.4.1 返回const值的意义
展开
代码语言:C++
自动换行
AI代码解释
const int getValue() { return 10; }
int main() {
getValue() = 20; // 错误:不能修改返回的临时常量
const int x = getValue(); // 正确
return 0;
}
对基本类型而言,返回const值意义不大,但对类类型可防止意外赋值:
展开
代码语言:C++
自动换行
AI代码解释
class BigNumber {
public:
BigNumber operator+(const BigNumber& other) const;
};
BigNumber a, b, c;
(a + b) = c; // 如果返回非const,这行会意外通过编译!
2.4.2 返回常量指针/引用
功能详解:
-
返回const指针/引用可防止外部修改内部数据
-
常用于类的getter方法,提供只读访问
-
避免返回内部临时对象的引用(悬空引用风险)
正确示例:
展开
代码语言:C++
自动换行
AI代码解释
class StringList {
private:
std::vector<std::string> items;
public:
// 返回const引用:避免拷贝,同时防止修改
const std::string& get(int index) const {
if (index >= 0 && index < items.size())
return items[index];
throw std::out_of_range("Index out of bounds");
}
// 返回const指针:指向内部静态数据
const char* getDefaultString() const {
static const char* defaultStr = "default";
return defaultStr; // 安全:静态变量生命周期长
}
};
常见错误:
代码语言:C++
自动换行
AI代码解释
const int& getTemporaryValue() {
int x = 10;
return x; // 危险:返回局部变量引用,函数结束后变为悬空引用
}
2.5 const 成员函数
2.5.1 功能与实现机制
const成员函数是C++常量正确性的核心机制,具有以下特性:
-
不能修改非mutable成员变量
-
不能调用非const成员函数
-
可以被const对象和非const对象调用
-
非const成员函数只能被非const对象调用
编译器实现原理:
const成员函数的this指针类型为const Class* const,而非const成员函数为Class* const,因此在const成员函数中无法修改成员变量。
2.5.2 mutable关键字的正确使用
mutable关键字允许const成员函数修改特定成员变量,通常用于:
-
缓存计算结果
-
跟踪对象访问次数
-
实现线程同步的互斥量
展开
代码语言:C++
自动换行
AI代码解释
class Cache {
private:
mutable std::map<std::string, Data> cache; // 缓存可在const函数中修改
mutable std::mutex mtx; // 互斥量可在const函数中锁定
mutable int accessCount = 0; // 访问计数可修改
public:
const Data& get(const std::string& key) const {
std::lock_guard<std::mutex> lock(mtx); // 正确:锁定mutable互斥量
accessCount++; // 正确:修改mutable成员
auto it = cache.find(key);
if (it != cache.end()) {
return it->second;
}
// 计算并缓存结果(修改mutable缓存)
Data result = computeData(key);
cache[key] = result;
return cache[key];
}
int getAccessCount() const { return accessCount; }
};
2.5.3 成员函数const重载
展开
代码语言:C++
自动换行
AI代码解释
class TextEditor {
private:
std::string text;
public:
// const版本:供const对象调用,返回const引用
const std::string& getText() const {
std::cout << "const getText() called\n";
return text;
}
// 非const版本:供非const对象调用,返回非const引用
std::string& getText() {
std::cout << "non-const getText() called\n";
return text;
}
};
int main() {
TextEditor editor;
const TextEditor constEditor;
editor.getText() = "new text"; // 正确:调用非const版本
// constEditor.getText() = "text"; // 错误:const版本返回const引用
return 0;
}
2.6 constexpr (C++11/14/17扩展)
2.6.1 constexpr与const的区别
| 特性 | const | constexpr (C++17) |
|---|---|---|
| 计算时机 | 通常运行时(除非编译期常量) | 强制编译期计算(可能退化为运行时) |
| 初始化 | 允许运行时初始化 | 必须编译期可计算 |
| 函数能力 | 无 | 可编写编译期执行的复杂函数 |
2.6.2 constexpr的高级应用
展开
代码语言:C++
自动换行
AI代码解释
// constexpr函数(C++14起支持复杂逻辑)
constexpr int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1); // C++14起支持递归
}
// constexpr变量(编译期计算)
constexpr int FACT_5 = factorial(5); // 编译期计算为120
// constexpr构造函数与对象
class Point {
public:
constexpr Point(double x, double y) : x(x), y(y) {}
constexpr double distance() const { return x*x + y*y; }
private:
double x, y;
};
constexpr Point ORIGIN(0, 0);
constexpr double ORIGIN_DISTANCE = ORIGIN.distance(); // 编译期计算
// constexpr if (C++17):编译期条件分支
template<typename T>
constexpr auto getValue(T t) {
if constexpr (std::is_integral_v<T>) {
return t * 2; // 整数类型处理
} else {
return t + 2; // 其他类型处理
}
}
常见问题:
展开
代码语言:C++
自动换行
AI代码解释
// C++11中constexpr函数限制(单return语句)
constexpr int sum(int a, int b) {
// if (a < 0) a = -a; // C++11错误:constexpr函数不允许if语句
return a + b;
}
// 正确:C++14起支持完整控制流
constexpr int absoluteSum(int a, int b) {
if (a < 0) a = -a;
if (b < 0) b = -b;
return a + b;
}
3. const 正确性与最佳实践
3.1 完整的const正确性体系
const正确性指一套编程规范,确保:
-
不应修改的对象声明为const
-
不修改成员变量的成员函数声明为const
-
不修改参数的函数参数声明为const
const正确性的好处:
-
编译期检测错误,提高程序可靠性
-
明确接口意图,提高代码可读性
-
允许编译器进行更多优化
-
支持const对象的使用
更多推荐

所有评论(0)