从立即函数返回std::vector:哪个编译器符合C++标准?
consteval函数返回std::vector的编译差异:哪个编译器符合C++标准?
自C20起,std::vector可用于常量表达式,标准明确允许在常量表达式求值结束前释放所有动态分配内存的前提下进行内存分配。但在consteval立即函数的场景中,不同编译器出现了行为差异:示例中consteval函数返回非空std::vector,并用static_assert验证其大小,该代码可在Clang搭配libc下编译通过,但MSVC和GCC均报错。
示例代码
consteval auto getVec() { return std::vector<int>(9); } static_assert( getVec().size() == 9 );
各编译器报错信息
- MSVC报错:
error C7595: 'getVec': call to immediate function is not a constant expression
note: (sub-)object points to memory which was heap allocated during constant evaluation
fatal error C1903: unable to recover from previous error(s); stopping compilation - GCC报错:
error: 'getVec()()' is not a constant expression because it refers to a result of 'operator new'
结论:Clang+libc++的行为符合标准
根据C++20及后续标准的规则:
- 常量表达式中允许动态内存分配,核心要求是所有分配的内存必须在常量表达式求值完成前被释放。
- 本例中,
getVec()返回的std::vector是临时对象,它的析构函数会在static_assert的常量表达式求值结束前执行——也就是vector的动态内存会被及时释放,完全满足标准的约束条件。
MSVC和GCC的报错属于实现层面的暂时缺陷,它们未正确识别临时vector的内存会在常量表达式结束前被释放的事实;而Clang+libc++的实现正确适配了标准规则,因此允许该代码编译。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

