我已经习惯了这样一个事实: const 引用会延长临时的生命周期,直到引用超出范围:
class X {};
{
X const & x = X();
// Lifetime of x extended to the end of the scope
// in which x is declared because it was declared
// as a *const* reference
}
...而且我也知道临时会一直存在,直到创建它的表达式结束:
// Contrived example to make a point about lifetime of a temporary in an expression
class Y
{
public:
Y() : y(5) {}
Y & operator+=(int const & rhs)
{
y += rhs;
return *this;
}
int foo() { return y; }
private:
int y;
};
// n in the following line of code is 11 and the code is valid
// - the lifetime of the temporary persists to the end of the expression
int n = (Y() += 6).foo();
假设我对上述两个方面都是正确的,我怀疑函数参数列表中创建的临时值是否会在函数调用的生命周期内持续存在,即使它绑定到非 -const reference:
class X {};
void foo(X & x)
{
// x is valid in this function,
// even though the parameter is declared
// as a *non*-const reference - correct?
}
// Valid, I think, even though the function parameter
// is declared as a **non**-const reference
// - because the lifetime of the temporary persists until the expression
// is fully evaluated - right?
foo(X());
我认为我的经验和理解是正确的 - 将函数参数列表中创建的临时值绑定到非 -const引用参数是安全的。
但我想确认我是对的,因为我无法在任何地方找到 explicity 这个问题。
谢谢!
答案 0 :(得分:3)
当然你是对的。
标准:
12.2临时对象[class.temporary]
[...]
有两种情况下,临时表在不同于完整表达结束时被摧毁。
第一个上下文是调用默认构造函数来初始化数组的元素。如果 构造函数有一个或多个默认参数,破坏默认情况下创建的每个临时值 如果有的话,参数在构造下一个数组元素之前被排序 第二个上下文是引用绑定到临时的。引用绑定的临时值或作为绑定引用的子对象的完整对象的临时值在引用的生存期内持续存在,除了:
- 构造函数的ctor-initializer(12.6.2)中的引用成员的临时绑定将持续存在,直到构造函数退出。
- 函数调用(5.2.2)中的引用参数的临时绑定将持续到包含该调用的完整表达式完成为止。
- 不延长函数返回语句(6.6.3)中返回值临时绑定的生存期;临时在return语句中的完整表达结束时被销毁 - 临时绑定到new-initializer(5.3.4)中的引用会一直存在,直到完成 包含new-initializer的full-expression。
想再使用一个级别的构造函数和存储引用的对象来再次提出问题吗?
答案 1 :(得分:2)
Deduplicator给了语言律师答案,这里是实施细节答案:
如果通过引用传递任何对象,则实际上是将指针传递给该对象。由于调用者只传递指向对象的指针,因此引用传递的对象必须由调用者构建。
另一方面,被调用者只能看到传入的指针。它没有看到调用者如何构造了传递指针的对象。这个对象可能是临时的(仅在const
引用的情况下,因为temporaries不能作为非const引用传递),或者是一个带有函数作用域的变量,它可能是一个已经传递给通过其调用者调用者,它甚至可以是分配有new
的对象。因此,它不能破坏对象,因为它不知道如何。
因此,在被调用者将控制权返回给调用者之后,由调用者清理临时 - 通过引用传入的任何内容必须对被调用者的整个运行时生效。< / p>
请注意,整个参数完全不知道引用是否为const
。