Skip to content

const

在 C 和 C++ 中,const 有显著的区别。主要差异如下:

1. 默认作用域链接性

  • Cconst 全局变量默认具有外部链接(external linkage)

    c
    // file1.c
    const int MAX = 100;  // 外部链接,其他文件可见
    
    // file2.c
    extern const int MAX;  // 正确,可以访问
  • C++const 全局变量默认具有内部链接(internal linkage)

    cpp
    // file1.cpp
    const int MAX = 100;  // 内部链接,仅在当前文件可见
    
    // file2.cpp
    extern const int MAX;  // 链接错误!找不到定义

    在 C++ 中需要显式使用 extern

    cpp
    // file1.cpp
    extern const int MAX = 100;  // 外部链接
    
    // file2.cpp
    extern const int MAX;  // 正确

2. 常量表达式处理

  • Cconst 变量不是编译时常量表达式

    c
    const int size = 10;
    int arr[size];  // C99 之前错误,size 不是常量表达式
  • C++const 变量是编译时常量表达式(如果初始化值是常量)

    cpp
    const int size = 10;
    int arr[size];  // 正确,size 是常量表达式

    在 C++11 之后,使用 constexpr 更明确。

3. 与指针的关系

虽然语法相似,但类型系统更严格:

cpp
// C++
const int* p1;        // 指向常量的指针
int const* p2;        // 同上
int* const p3;        // 常量指针
const int* const p4;  // 指向常量的常量指针

// C 语法相同,但 C++ 类型检查更严格
void foo(const int* p) {
    int* q = p;  // C++ 错误,C 警告(需要强制转换)
}

4. 在函数中的应用

C++ 特有的用法:

常量成员函数

cpp
class MyClass {
    int value;
public:
    int get() const {  // 承诺不修改对象
        return value;
    }
};

const MyClass obj;
obj.get();  // 正确,调用常量成员函数

常量引用参数

cpp
void func(const std::string& str);  // 避免复制,承诺不修改

5. 初始化要求

  • Cconst 变量可以不初始化(但默认值不确定)

    c
    const int x;  // C 允许,值未定义
  • C++const 变量必须初始化

    cpp
    const int x;  // C++ 错误:未初始化的常量
    const int y = 5;  // 正确

6. 字符串字面量

c
// C
const char* str = "hello";
str[0] = 'H';  // 运行时错误(未定义行为)

// C++
const char* str = "hello";  // 字符串字面量是 const char[]
char* str2 = "hello";       // C++ 错误,需要强制转换

7. 与宏定义的比较

c
// C 中常用宏定义常量
#define MAX_SIZE 100

// C++ 推荐使用 const
const int MAX_SIZE = 100;
constexpr int MAX_SIZE2 = 100;  // C++11

8. 类型转换规则

  • C:允许从 const T* 隐式转换为 T*(会有警告)

    c
    const int* p1;
    int* p2 = p1;  // 警告,但允许
  • C++:不允许隐式转换,需要显式 const_cast

    cpp
    const int* p1;
    int* p2 = p1;  // 错误
    int* p3 = const_cast<int*>(p1);  // 显式转换

总结对比表

特性CC++
默认链接性外部链接内部链接
常量表达式不是(C99前)
函数中的使用有限常量成员函数、引用参数
初始化要求可选必须
类型安全性较宽松严格
字符串字面量char*const char*
数组大小不能用于静态数组(C99前)可以

建议

  1. C 中使用 const 主要表示"只读",不是真正的编译时常量
  2. C++const 是类型系统的一部分,提供更强的保证
  3. C++11 后,对于编译时常量,优先使用 constexpr
  4. 在多文件项目中,注意 const 的链接性差异

理解这些差异有助于编写更安全、可移植的代码。