constexpr返回数组,gcc警告

Xen*_*eno 8 c++ arrays gcc gcc-warning constexpr

我写了一个返回数组的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;
}
Run Code Online (Sandbox Code Playgroud)

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' };
Run Code Online (Sandbox Code Playgroud)

在这种情况下警告是否正确?从这样的constexpr函数返回数组是不正确的,即使该函数在运行时从未实际调用过,只是在编译期间?

Sha*_*our 2

clang 3.4不编译此代码,因为sum(get_str())它不是constexpr,据我所知clang,这一行在这里是正确的(实时查看):

\n\n
constexpr int s = sum(get_str());\n
Run Code Online (Sandbox Code Playgroud)\n\n

生成以下错误:

\n\n
error: constexpr variable \'s\' must be initialized by a constant expression\nconstexpr int s = sum(get_str());\n              ^   ~~~~~~~~~~~~~~\n\nnote: read of temporary whose lifetime has ended\nreturn str[0] + str[1] + str[2] + str[3] \n       ^\n
Run Code Online (Sandbox Code Playgroud)\n\n

constexpr由于两个原因,它是无效的。这会调用未定义的行为,并且在常量表达式中明确不允许这样做,总结一下C++ 标准草案部分5.19说:

\n\n
\n

条件表达式 e 是核心常量表达式,除非 e 的计算,

\n
\n\n

并包含以下项目符号:

\n\n
\n

具有未定义行为的操作

\n
\n\n

在其生命周期之外进行访问将是。我们知道,在这种情况下,临时对象的生命周期不会延长12.2 部分可知:

\n\n
\n

第二个上下文是当引用绑定到临时对象时。117 引用绑定到的临时对象或引用绑定到的子对象的完整对象的临时对象在生命周期内持续存在参考除了

\n
\n\n

并包括以下项目符号:

\n\n
\n

绑定到函数 return 语句 (6.6.3) 中返回值的临时变量的生命周期不会延长;临时变量在 return 语句中完整表达式的末尾被销毁。

\n
\n\n

因此,虽然确实不能保证常量表达式在翻译时被评估,但我们在5.19 常量表达式部分中有一个注释提到了这一点(强调我的未来):

\n\n
\n

注意:常量表达式可以是在翻译过程中求值。\xe2\x80\x94end\n note ]

\n
\n\n

即使得到保证,我们仍然不会被允许调用未定义的行为。

\n\n

第二个问题是 constexpr 引用必须是静态存储持续时间的对象或函数,cppreference在其核心常量表达式部分中提到了这一点中提到了这一点:

\n\n
\n

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

\n
\n\n

据我所知,这在5.19 常量表达式第 4段中有所介绍段中有所介绍,其中说道:

\n\n
\n

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

\n
\n