找回密码
 register

QQ登录

只需一步,快速开始

查看: 22|回复: 0

[C++] C++中的const又玩出了新花样

[复制链接]

[C++] C++中的const又玩出了新花样

[复制链接]
  • 打卡等级:热心大叔
  • 打卡总天数:243
  • 打卡月天数:20
  • 打卡总奖励:241
  • 最近打卡:2025-07-22 08:02:38
Waylee

主题

0

回帖

2万

积分

仙帝

积分
26280
Waylee 2025-7-19 02:03 | 显示全部楼层 |阅读模式 | Google Chrome | Windows 10

马上注册,查看网站隐藏内容!!

您需要 登录 才可以下载或查看,没有账号?register

×

在 C 语言中,const 用来修饰变量,表示该变量值不可被修改,我们通常称之为常量(Constant)。《C 语言 const 的用法详解》一节已对此进行了详细阐述。在 C++ 中,const 的基本含义不变,但在编译器处理和链接过程上有一些重要差异,以下针对最主要的两点进行说明。


1. 编译阶段的“替换” vs. 运行阶段的内存读取

const int m = 10;
int n = m;
  • 在 C 语言(C99 及以后)中const int m 仍是一个内存对象;执行 int n = m; 时,编译器生成代码读取 m 所在内存,然后将其值存入 n
  • 在 C++ 中,编译器会将 m 看作编译期常量,将 int n = m; 等价替换为 int n = 10;,不再生成对内存的读取指令——这与 #define m 10 的效果类似。

这样做的优点在于减少运行时开销,但缺点是如果强制通过指针修改了 m,随后对 m 的访问仍会使用编译期间替换的值:

// test.c
#include <stdio.h>
int main() {
    const int n = 10;
    int *p = (int*)&n;
    *p = 99;
    printf("C 输出: %d\n", n);  // 输出 99(读取内存)
    return 0;
}
// test.cpp
#include <stdio.h>
int main() {
    const int n = 10;
    int *p = (int*)&n;
    *p = 99;
    printf("C++ 输出: %d\n", n);  // 输出 10(编译期替换)
    return 0;
}

注意:虽然 const 在语法层面阻止修改,但可以通过强制转换指针绕过。此处示例仅用于说明编译器处理差异,实际代码中请勿滥用。


2. 全局 const 变量的链接属性

  • C 语言:全局变量默认具有外部链接(external linkage),即使使用了 const,在其他源文件中使用 extern 声明后也可访问。

  • C++:全局 const 对象默认具有内部链接(internal linkage),等同于隐含了 static,只能在声明它的翻译单元(源文件)内可见。若将其放入头文件,多次包含也不会导致重定义错误:

    // module.h
    const int N = 10;
    void func();
    
    // module.cpp
    #include "module.h"
    void func() { printf("module: %d\n", N); }
    
    // main.cpp
    #include "module.h"
    int main() {
      func();
      printf("main: %d\n", N);
      return 0;
    }

    若要在 C++ 中让全局 const 具有外部链接,可显式添加 extern(GCC 支持,但 MSVC/Clang 对此行为有所差异):

    // globals.h
    extern const int M = 20;  // 显式外部链接

3. C++11 及以后的 constexpr

从 C++11 起,引入了 constexpr 关键字,用于定义常量表达式:

  • constexpr 对象在符合规则时可以用于编译期计算,比 const 更严格。
  • 可修饰函数、构造函数、变量。
constexpr int square(int x) { return x * x; }
constexpr int SIZE = square(5);  // 在编译期求值,等同于 25

使用 constexpr 可以更好地表达“编译期常量”的语义,并在泛型编程和模板元编程中发挥重要作用。


4. 总结

  1. 语义清晰:在 C++ 中,优先使用 constexpr(C++11+)和 const,而非 #define,以获得类型检查和调试友好性。
  2. 注意链接:了解全局 const 的内部链接特性,必要时可用 extern 或命名空间管理可见性。
  3. 不要滥用指针修改:即使可以通过指针修改 const 对象,也严重违反常量语义,应极力避免。
您需要登录后才可以回帖 登录 | register

本版积分规则

雪舞知识库 | 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 |网站地图|天天打卡

GMT+8, 2025-7-22 19:08 , Processed in 0.104555 second(s), 6 queries , Redis On.

Powered by XueWu Licensed

Copyright © Tencent Cloud.

快速回复 返回顶部 返回列表