为什么const引用不能延长通过函数传递的临时对象的寿命?
在下面的简单示例中,为什么不能将ref2
绑定到min(x,y+1)
的结果?
In the following simple example, why can't ref2
be bound to the result of min(x,y+1)
?
#include <cstdio>
template< typename T > const T& min(const T& a, const T& b){ return a < b ? a : b ; }
int main(){
int x = 10, y = 2;
const int& ref = min(x,y); //OK
const int& ref2 = min(x,y+1); //NOT OK, WHY?
return ref2; // Compiles to return 0
}
实时示例-产生:
main:
xor eax, eax
ret
我认为,下面的示例更好地描述了一种情况.
Below example better described a situation, I think.
#include <stdio.h>
template< typename T >
constexpr T const& min( T const& a, T const& b ) { return a < b ? a : b ; }
constexpr int x = 10;
constexpr int y = 2;
constexpr int const& ref = min(x,y); // OK
constexpr int const& ref2 = min(x,y+1); // Compiler Error
int main()
{
return 0;
}
实时示例产生:
<source>:14:38: error: '<anonymous>' is not a constant expression
constexpr int const& ref2 = min(x,y+1);
^
Compiler returned: 1
这是设计使然.简而言之,只有与 直接绑定的命名引用会延长其寿命.
It's by design. In a nutshell, only the named reference to which the temporary is bound directly will extend its lifetime.
[class.temporary]
5在三种情况下, 与完整表达的结束点不同. [...]
5 There are three contexts in which temporaries are destroyed at a different point than the end of the full-expression. [...]
6第三种情况是引用绑定到临时项时. 引用绑定到的临时对象或引用的临时对象 引用绑定到的子对象的完整对象 在参考的有效期内持续存在,除了:
6 The third context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:
- 绑定到函数调用中的参考参数的临时对象将持续存在,直到包含以下内容的完整表达式完成 电话.
- 在函数return语句中,临时绑定到返回值的生存期不会延长;临时被毁 在return语句中的完整表达式的末尾.
- [...]
- A temporary object bound to a reference parameter in a function call persists until the completion of the full-expression containing the call.
- The lifetime of a temporary bound to the returned value in a function return statement is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
- [...]
您没有直接绑定到ref2
,甚至可以通过return语句将其传递.该标准明确表示不会延长使用寿命.在某种程度上使某些优化成为可能.但是最终,因为很难理解在引用传入和传出函数时应该扩展哪个临时对象.
You didn't bind directly to ref2
, and you even pass it via a return statement. The standard explicitly says it won't extend the lifetime. In part to make certain optimizations possible. But ultimately, because keeping track of which temporary should be extended when a reference is passed in and out of functions is intractable in general.
由于编译器会在程序没有任何未定义行为的前提下进行积极的优化,因此您可能会看到这种情况.未定义在其生存期之外访问值的操作,这是return ref2;
所要做的,并且由于该行为是未定义的,因此简单地返回零便是有效的行为.编译器不会破坏合同.
Since compilers may optimize aggressively on the assumption that your program exhibits no undefined behavior, you see a possible manifestation of that. Accessing a value outside its lifetime is undefined, this is what return ref2;
does, and since the behavior is undefined, simply returning zero is a valid behavior to exhibit. No contract is broken by the compiler.