我写了一个返回数组的constexpr函数。
#include <iostream>
constexpr auto get_str(void)
-> const char(&)[4] {
return { 'T', 'E', 'S', 'T' };
}
constexpr int sum(const char(&str)[4]){
return str[0] + str[1] + str[2] + str[3];
}
int main(void){
constexpr int s = sum(get_str());
std::cout << s << std::endl;
return 0;
}
g ++ 4.8正确编译代码,但发出以下警告:
test.cpp: In function ‘constexpr const char (& get_str())[4]’:
test.cpp:5:30: warning: returning reference to temporary [-Wreturn-local-addr]
return { 'T', 'E', 'S', 'T' };
在这种情况下警告是否正确?从这样的constexpr函数返回一个数组是不正确的,即使该函数在运行时从未实际调用过,只是在编译期间?
答案 0 :(得分:2)
clang 3.4
无法编译此代码,因为sum(get_str())
不是 constexpr ,据我所知,clang
在这里是正确的,这一行(< EM> see it live 的):
constexpr int s = sum(get_str());
生成以下错误:
error: constexpr variable 's' must be initialized by a constant expression
constexpr int s = sum(get_str());
^ ~~~~~~~~~~~~~~
note: read of temporary whose lifetime has ended
return str[0] + str[1] + str[2] + str[3]
^
由于两个原因,它不是有效的constexpr
。这会调用未定义的行为,这是explicitly disallowed in a constant expression,总结the draft C++ standard部分5.19
说:
条件表达式e是核心常量表达式,除非评估e,
并包含以下项目符号:
具有未定义行为的操作
在其生命周期之外进行访问。在这种情况下,我们知道临时的生命周期不会从12.2
临时对象部分扩展,其中包含:
第二个上下文是指一个引用绑定到一个临时的.17 临时引用的临时或临时的 引用绑定到的子对象的完整对象 除
外,在参考文件的生命周期内持续存在
并包含以下项目符号:
临时绑定到函数中返回值的生命周期 退货声明(6.6.3)未延期;临时被摧毁 在return语句中的完整表达式的末尾。
因此,虽然确实常量表达式确实无法在翻译时进行评估,但我们在5.19
常量表达式部分中有一个注释提到这个(强调我的前进):
注意:在translation.-end期间可以>>评估常量表达式 注意]
即使有保证,我们仍然不允许调用未定义的行为。
第二个问题是constexpr引用必须是静态存储持续时间或函数的对象,cppreference在core constant expression section中提及:
引用常量表达式是左值核心常量表达式 指定具有静态存储持续时间或函数的对象
据我所知,5.19
常量表达式段 4 中包含了以下内容:
引用类型的每个非静态数据成员引用一个对象 静态存储持续时间或函数,
答案 1 :(得分:1)
该函数永远不会在运行时实际调用,仅在执行期间 汇编
不能保证在所有标准。编译器完全有权在运行时调用它。
constexpr
temporaries永远不会死如果编译器在编译时调用它。编译器没有义务。