什么决定临时对象的生命周期何时扩展到 const 引用或右值引用?
What determines when the lifetimes of temporaries get extended into const references or rvalue references?
鉴于:
struct hurg { ... };
hurg get_hurg() { return hurg(); }
hurg&& get_mhurg() { return hurg(); }
我的理解 and experimenting 表明以下是 不是 未定义的行为(编辑:感谢答案,事实证明我错了 get_mhurg()
示例 是 未定义的行为):
{
const hurg& a = get_hurg();
hurg&& b = get_hurg();
const hurg& c = get_mhurg();
hurg&& d = get_mhurg();
// do stuff with a, b, c, d
}
// a, b, c, d are now destructed
即get_hurg()
和get_mhurg()
返回的临时hurg
对象的生命周期延长到作用域结束。
但是,在(来自 的函数)的情况下:
template <typename T>
auto id(T&& x) -> decltype(auto) { return decltype(x)(x); }
像这样使用它:
{
const hurg& x = id(hurg());
// the hurg() 'x' refers to is already destructed
hurg&& y = id(hurg());
// the hurg() 'y' refers to is already destructed
// undefined behavior: use 'x' and 'y'
}
在这种情况下,hurg
的生命周期不会 延长。
通常什么时候延长临时对象的生命周期?并且,特别是,什么时候将函数的结果绑定到 const 左值引用或右值引用是安全的?
更具体地说,id
案例中到底发生了什么?
来自[class.temporary]:
There are two contexts in which temporaries are destroyed at a different point than the end of the fullexpression.
The first context is when a default constructor is called to initialize an element of an array [...]
The second 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 sub-object to which the reference is bound persists
for the lifetime of the reference except:
(5.1) — A temporary object bound to a reference parameter in a function call (5.2.2) persists until the completion
of the full-expression containing the call.
(5.2) — The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not
extended; the temporary is destroyed at the end of the full-expression in the return statement.
(5.3) — A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of the
full-expression containing the new-initializer.
所以有两件事。首先, get_mhurg
是未定义的行为。您要返回的临时文件的生命周期 不会 延长。其次,传递给 id
的临时变量持续到包含函数调用的完整表达式结束, 但没有进一步 。与 get_mhurg
一样,临时文件不会被完全扩展。所以这也是未定义的行为。
My understanding and experimenting shows that the following is not
undefined behavior:
嗯,你的理解和实验是错误的。明智的提示 - 不要尝试未定义的行为。例如,您的实验可能会随机碰巧表明它是明确定义的行为,这是未定义行为的可能结果之一。
使用 get_mhurg()
的 return 值是未定义的行为。您正在访问其创建范围之外的临时文件 hurg()
。
id
的情况表明延长生命周期是愚蠢的。
具体来说,生命周期延长仅直接适用于值。它从不适用于任何类型的引用。您必须使用一个值来初始化引用。 id
没有 return 值,因此不应用生命周期延长。
鉴于:
struct hurg { ... };
hurg get_hurg() { return hurg(); }
hurg&& get_mhurg() { return hurg(); }
我的理解 and experimenting 表明以下是 不是 未定义的行为(编辑:感谢答案,事实证明我错了 get_mhurg()
示例 是 未定义的行为):
{
const hurg& a = get_hurg();
hurg&& b = get_hurg();
const hurg& c = get_mhurg();
hurg&& d = get_mhurg();
// do stuff with a, b, c, d
}
// a, b, c, d are now destructed
即get_hurg()
和get_mhurg()
返回的临时hurg
对象的生命周期延长到作用域结束。
但是,在(来自
template <typename T>
auto id(T&& x) -> decltype(auto) { return decltype(x)(x); }
像这样使用它:
{
const hurg& x = id(hurg());
// the hurg() 'x' refers to is already destructed
hurg&& y = id(hurg());
// the hurg() 'y' refers to is already destructed
// undefined behavior: use 'x' and 'y'
}
在这种情况下,hurg
的生命周期不会 延长。
通常什么时候延长临时对象的生命周期?并且,特别是,什么时候将函数的结果绑定到 const 左值引用或右值引用是安全的?
更具体地说,id
案例中到底发生了什么?
来自[class.temporary]:
There are two contexts in which temporaries are destroyed at a different point than the end of the fullexpression. The first context is when a default constructor is called to initialize an element of an array [...]
The second 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 sub-object to which the reference is bound persists for the lifetime of the reference except:
(5.1) — A temporary object bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.
(5.2) — The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
(5.3) — A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of the full-expression containing the new-initializer.
所以有两件事。首先, get_mhurg
是未定义的行为。您要返回的临时文件的生命周期 不会 延长。其次,传递给 id
的临时变量持续到包含函数调用的完整表达式结束, 但没有进一步 。与 get_mhurg
一样,临时文件不会被完全扩展。所以这也是未定义的行为。
My understanding and experimenting shows that the following is not undefined behavior:
嗯,你的理解和实验是错误的。明智的提示 - 不要尝试未定义的行为。例如,您的实验可能会随机碰巧表明它是明确定义的行为,这是未定义行为的可能结果之一。
使用 get_mhurg()
的 return 值是未定义的行为。您正在访问其创建范围之外的临时文件 hurg()
。
id
的情况表明延长生命周期是愚蠢的。
具体来说,生命周期延长仅直接适用于值。它从不适用于任何类型的引用。您必须使用一个值来初始化引用。 id
没有 return 值,因此不应用生命周期延长。