C++的const 增强

在C++中,const 关键字相较于C语言有显著增强,尤其在类型安全编译期优化方面。下面我会从常量定义、指针常量、函数修饰等角度详细对比C与C++的差异,并通过代码示例解析其设计哲学。


📌 核心增强点总览

特性C语言C++增强
常量定义const变量默认为外部链接const变量默认为内部链接(更像static const
指针常量仅支持基本const修饰更严格的类型检查,支持const成员函数
常量表达式不支持编译期常量表达式(C99前)支持constexpr(C++11引入)
函数参数与返回值有限使用广泛用于引用传递、避免拷贝(如const T&

1. ​常量定义的链接性

C语言的const行为
// file1.c
const int MAX_SIZE = 100;  // 外部链接(其他文件可通过extern访问)

// file2.c
extern const int MAX_SIZE; // 链接到file1的MAX_SIZE

问题​:多个文件定义同名const变量会导致链接冲突。

C++的改进
// file1.cpp
const int MAX_SIZE = 100;  // 默认内部链接(仅在当前文件可见)

// file2.cpp
extern const int MAX_SIZE; // 错误!无法链接到file1的MAX_SIZE

解决方案​:如需跨文件共享常量,必须显式声明为extern

// header.h
extern const int GLOBAL_SIZE; // 声明

// file1.cpp
extern const int GLOBAL_SIZE = 200; // 定义

2. ​指针常量的严格类型检查

C与C++的通用语法
const int* p1;       // 指向常量的指针(指针可变,数据不可变)
int* const p2 = &x;  // 指针常量(指针不可变,数据可变)
const int* const p3; // 指向常量的指针常量(两者均不可变)
C++的额外增强

类型安全​:C++禁止从const T*T*的隐式转换(C语言仅警告):

const int a = 10;
int* p = &a;         // C中警告,C++直接报错
int* q = (int*)&a;   // 必须显式强制转换

3. const成员函数(C++独有)

类的成员函数可声明为const,表示不修改对象状态:

class Circle {
    double radius;
public:
    double getArea() const { // 承诺不修改成员变量
        return 3.14 * radius * radius;
    }
};

违反约束会直接编译报错​:

double getArea() const {
    radius = 10; // 错误!const函数内不能修改成员
    return 3.14 * radius * radius;
}

4. ​常量表达式constexpr(C++11)​

C++允许编译期计算常量表达式:

constexpr int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

int arr[factorial(5)]; // 数组大小在编译期确定为120

C语言(C99前)只能用宏或字面量:

#define FACTORIAL_5 120
int arr[FACTORIAL_5];

🌰 实际应用场景

场景1:函数参数保护
void print(const std::string& s) {
    // s不能被意外修改(如s.clear()会报错)
    std::cout << s;
}
场景2:返回const防止误操作
const int& getValue(const MyClass& obj) {
    return obj.internalValue; // 返回的引用不可修改
}

⚠️ 常见陷阱

  1. ​**const与宏定义的取舍**​

    const int MAX = 100;  // 推荐(类型安全、调试可见)
    #define MAX 100       // 不推荐(无类型、直接替换)
  2. ​**const指针的声明顺序**​

    int a = 1, b = 2;
    const int* p1 = &a; // 指向常量(*p1不可改)
    int* const p2 = &a; // 指针常量(p2不可改)
    p1 = &b; // OK
    *p2 = 3; // OK

✏️ 动手练习

  1. 编写一个Student类,包含const成员函数getName()和非const函数setName()
  2. 尝试定义一个constexpr函数计算斐波那契数列,并用于初始化数组。
参考答案
// 练习1
class Student {
    std::string name;
public:
    const std::string& getName() const { return name; }
    void setName(const std::string& newName) { name = newName; }
};

// 练习2
constexpr int fib(int n) {
    return (n <= 1) ? n : fib(n - 1) + fib(n - 2);
}

int main() {
    int arr[fib(5)]; // 数组大小为5
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shanglong_gc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值