c++ const和static区别_c++面试常考关键字

const管可变性,static管存储期与链接属性;二者维度不同,可共存但不可互替,如static const仅表示静态存储+只读,非编译期常量。

const 和 static 根本不是一类东西——一个管“能不能改”,一个管“在哪存、谁可见、活多久”。面试一问就卡壳,往往是因为把它们当成了同类修饰符去对比。其实只要分清维度,就能一次理清。

函数内部:static 局部变量 vs const 局部变量

两者行为完全不重叠:

  • static int counter = 0;:每次调用函数时,counter 不会重置,值持续累加;内存在程序启动时分配,生命周期贯穿整个运行期。
  • const int MAX_RETRY = 3;:只读,但每次函数调用都“重新声明”(实际编译器通常优化掉),作用域仅限当前函数,退出即不可访问。
  • ⚠️ 常见错误:static const int x = 42; 在函数内合法,但有人误以为它“全局常量化”了——其实它只是“静态存储 + 只读”,仍不能用于模板非类型参数(除非是 constexpr)。

类中成员:static 成员变量 vs const 成员变量

这是面试高频混淆点,关键看“属于谁”和“何时定值”:

  • static int s_count;:属于类本身,所有对象共享一份;必须在类外定义(如 int MyClass::s_count = 0;),否则链接时报 undefined reference
  • const int m_id;:属于每个对象,不同对象可有不同值;必须在构造函数初始化列表中赋值(如 MyClass(int id) : m_id(id) {}),不能在类内直接初始化(C++11 前)。
  • ? 协同用法:static constexpr int MAX_SIZE = 1024; 才是真正安全的“类级编译期常量”,可用于数组大小、模板参数,且无链接问题。

文件作用域:const 全局变量默认 internal linkage,static 全局变量也是

很多人以为 const 就是“全局公开”,其实 C++ 中:

  • const int CONFIG_VERSION = 1; 默认具有 internal linkage(相当于隐式加了 static),其他文件无法通过 extern const int CONFIG_VERSION; 访问——除非显式声明为 extern const int CONFIG_VERSION; 并在某处定义。
  • static int helper_flag; 明确限制为本文件可见,链接器不会导出符号,避免命名冲突。
  • ❌ 踩坑示例:头文件里写 const int LOG_LEVEL = 2; 并被多个 .cpp 包含 → 每个编译单元都生成一份副本,看似没问题,但若取地址(&LOG_LEVEL),可能因 ODR 违反导致未定义行为(尤其开启 LTO 时)。

成员函数:const 函数 vs static 函数,为什么不能同时用?

因为语义根本冲突:

  • void print() const;:承诺不修改 *this 对象状态,但仍需通过对象调用(隐含 this 参数)。
  • static void init();:不依赖任何对象,没有 this,连 const 修饰都无意义——它本来就不访问成员变量。
  • ? 编译器直接报错:static void foo() const 是非法语法(C++ 标准禁止),不是警告,是硬性约束。
  • ? 实际替代方案:若想提供“不依赖对象 + 不修改状态”的接口,用 static 就够了;若还需保证线程安全或封装逻辑,再配合 const 参数(如 static void process(const Data& d);)。

最易忽略的一点:static 控制的是**存储期与链接属性**,const 控制的是**可变性与类型契约**——它们可以共存(如 static const int),但绝不能互相替代。面试时若只答“一个不变、一个共享”,大概率会被追问底层机制;能讲清 linkage、ODR、constexpr 替代方案,才算真过关。