为何GCC 12.1.0中constexpr vector编译失败?cppreference显示支持
问题:constexpr std::vector编译失败的原因
我在cppreference的编译器支持页面看到constexpr vector是被支持的,但编写以下代码:
#include <vector> constexpr std::vector<int> vec{2, 3, 3, 3}; int main() { }
使用-std=gnu++2b编译时触发错误:
In file included from /usr/include/c++/12/vector:61, from test.cpp:1: /usr/include/c++/12/bits/allocator.h:182:50: error: ‘std::vector<int>(std::initializer_list<int>{((const int*)(& const int [4]{2, 3, 3, 3})), 4}, std::allocator<int>())’ is not a constant expression because it refers to a result of ‘operator new’ 182 | return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); | ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
我的GCC版本为gcc version 12.1.0 (Ubuntu 12.1.0-2ubuntu1~22.04),且__cpp_constexpr == 202110L,请问这是为什么?
解答
这是因为GCC 12.x对constexpr std::vector的支持存在限制:它允许在constexpr上下文中(比如constexpr函数、constexpr代码块)使用vector,但不支持将vector声明为静态存储期的constexpr对象(也就是全局变量)。
核心原因在于,C++20/23的constexpr容器允许编译期分配内存,但这类内存是临时的——编译结束后就会被释放,无法留存到运行时。而全局constexpr变量要求对象在运行时依然有效,这就产生了矛盾:编译期分配的内存无法存活到运行时,运行时再分配内存又不符合constexpr初始化的要求。
GCC 13及后续版本才完全支持静态存储期的constexpr std::vector,因为实现了编译期分配内存向运行时迁移的机制。在GCC 12中,你可以在constexpr函数内部使用vector,只要它的生命周期不延伸到运行时即可,比如:
#include <vector> constexpr int get_sum() { std::vector<int> vec{2, 3, 3, 3}; int sum = 0; for (int n : vec) sum += n; return sum; } // 编译期计算结果,运行时直接使用常量值 constexpr int sum = get_sum(); int main() { return sum; }
这段代码在GCC 12中可以正常编译,因为vector的生命周期完全局限在constexpr函数内部,不需要留存到运行时。
内容的提问来源于stack exchange,提问作者Andy Lee
相关产品推荐
相关产品推荐

