例如,除非incr()声明,否则下面的代码不会编译constexpr:
int incr(int& n) {
return ++n;
}
constexpr int foo() {
int n = 0;
incr(n);
return n;
}
Run Code Online (Sandbox Code Playgroud)
看看C++ 14中的§7.1.5/ 3,我们有:
constexpr函数的定义应满足以下约束条件:
(3.1) - 它不应是虚拟的(10.3);
(3.2) - 其返回类型应为字面类型;
(3.3) - 每个参数类型应为文字类型;
(3.4) - 其函数体应为= delete,= default或不包含的复合语句(3.4.1) - asm-definition,
(3.4.2) - goto语句,
(3.4.3) - try-block,或
(3.4.4) - 非文字类型的变量的定义或静态或线程存储持续时间或未执行初始化的时间.
(我知道应该避免返回对函数本地变量的地址/引用,并且程序永远不应该这样做.)
是否在未定义的行为中返回对局部变量/引用结果的引用?或者,只有在使用返回的引用(或"解除引用")时才会出现未定义的行为?
即在什么确切的声明(#1或#2或#3)不低于示例代码调用未定义行为?(我把每个理论都写在一起)
#include <iostream>
struct A
{
int m_i;
A():m_i(10)
{
}
};
A& foo()
{
A a;
a.m_i = 20;
return a;
}
int main()
{
foo(); // #1 - Not UB; return value was never used
A const &ref = foo(); // #2 - Not UB; return value still not yet used
std::cout<<ref.m_i; // #3 - UB: returned value is used
}
Run Code Online (Sandbox Code Playgroud)
我很想知道C++标准在这方面的规定.
我想要一个来自C++标准的引用,它基本上会告诉我哪个确切的语句使这个代码格式不正确.
关于具体实现如何处理这一问题的讨论是值得欢迎的,但正如我所说,一个理想的答案将引用C++标准中的一个参考,这可以毫无疑问地澄清这一点.
在这里的Stack Overflow答案中,Kerrek发布了以下代码.
Foo && g()
{
Foo y;
// return y; // error: cannot bind ‘Foo’ lvalue to ‘Foo&&’
return std::move(y); // OK type-wise (but undefined behaviour, thanks @GMNG)
}
Run Code Online (Sandbox Code Playgroud)
GManNickG指出这会导致未定义的行为.
克雷克补充道
真正; 除了前进和移动,你不会真正从任何东西返回&&.这是一个人为的例子.
令我困惑的是,C++ 11标准使用函数调用,该函数调用返回rvalue引用作为xvalue表达式的示例.
xvalue("eXpiring"值)也指对象,通常接近其生命周期的末尾(例如,可以移动其资源).xvalue是涉及rvalue引用的某些表达式的结果(8.3.2).[示例:调用返回类型为右值引用的函数的结果是xvalue. - 末端的例子]
那么,当确实在未定义的行为中返回rvalue引用结果时?是否总是导致未定义的行为,除了std::move和std::forward和标准只是简洁?或者您是否必须访问未定义行为的返回值才能生成结果?
*"何时"是指"在什么情况下".我意识到这里没有有意义的时间概念.