constexpr返回数组,gcc警告

时间:2014-08-31 19:56:49

标签: c++ arrays gcc constexpr gcc-warning

我写了一个返回数组的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函数返回一个数组是不正确的,即使该函数在运行时从未实际调用过,只是在编译期间?

2 个答案:

答案 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引用必须是静态存储持续时间或函数的对象,cppreferencecore constant expression section中提及:

  

引用常量表达式是左值核心常量表达式   指定具有静态存储持续时间或函数的对象

据我所知,5.19 常量表达式 4 中包含了以下内容:

  

引用类型的每个非静态数据成员引用一个对象   静态存储持续时间或函数,

答案 1 :(得分:1)

  

该函数永远不会在运行时实际调用,仅在执行期间   汇编

不能保证在所有标准。编译器完全有权在运行时调用它。

constexpr temporaries永远不会死如果编译器在编译时调用它。编译器没有义务。