静态数组需类外定义,类内仅声明;C++17起可用inline static在类内定义初始化,否则须在唯一.cpp文件中定义;数组大小必须为编译期常量,非常量表达式非法。

静态数组必须在类外定义
类内声明的 static 数组只是声明,不分配存储空间;必须在类外单独定义并初始化,否则链接时会报 undefined reference to 'ClassName::array_name'。
- 头文件中只写声明:
static int arr[3]; - 源文件(.cpp)中写定义+初始化:
int MyClass::arr[3] = {1, 2, 3}; - 若用
constexpr或constinit(C++20),仍需类外定义,仅初始化可放类内(但仅限字面量类型且有默认值)
初始化方式取决于数组元素类型
内置类型(如 int、double)支持聚合初始化;自定义类型需满足可默认构造或提供初始化器。
- 全零初始化:
int MyClass::arr[5]{};(注意是{},不是{0},后者只初始化首元素) - 指定初值:
std::string MyClass::names[2] = {"a", "b"};(要求std::string可隐式构造) - 动态初始化(C++17起):
inline static std::vector<int> vec = []{ return std::vector<int>(10, 42); }();</int></int>—— 但这已不是“数组”,而是对象
避免常见链接错误和 ODR 违反
多个编译单元包含同一头文件时,若把定义写在头里(哪怕加 inline),会导致 ODR 违反;而没定义则链接失败。
- 错误做法:在头文件里写
int MyClass::arr[3] = {0};→ 多个 .o 文件都含该定义 → 链接时报 duplicate symbol - 正确做法:定义只出现在一个 .cpp 文件中;或 C++17 起可用
inline static直接在类内定义:inline static int arr[3] = {1,2,3}; -
inline static是目前最简洁安全的方式,但需确认编译器支持(GCC 7+/Clang 5+/MSVC 2017)
静态数组大小不能依赖非 constexpr 表达式
类内声明时数组维度必须是常量表达式;类外定义时也不能用运行时值。
立即学习“C++免费学习笔记(深入)”;
- 合法:
static int arr[10];、static int arr[N];(其中N是constexpr) - 非法:
static int arr[n];(n是普通变量)、static int arr[func()];(func()非 constexpr) - 若尺寸不确定,改用
std::vector或std::array(后者尺寸仍需编译期确定)
inline static 虽好,但老项目可能卡在 C++14,得手动拆到 .cpp 里。


















