哪个标准措辞告诉我们,ref-to-const 临时寿命延长只"有效一次"?

Which standard wording tells us that ref-to-const temporary lifetime extension only "works once"?

本文关键字:有效 一次 标准 我们 ref-to-const      更新时间:2023-10-16

我在聊天中看到了以下示例:

#include <iostream>
struct foo { ~foo() { std::cout << "destroying!n"; } };
const foo& func(const foo& a, const foo&) { return a; }
int main()
{
  foo x;
  const foo& y = func(foo(), x);
  std::cout << "mainn";
}

输出:

destroying!
main
destroying!

它似乎证明了foo临时的生存期并没有扩展到整个main,即使它在该范围内绑定到了-const的引用。

那么,可以推测,寿命延长只"有效一次";也就是说,它在初始化func的参数时应用,但不会通过连续绑定传递。

我的解释正确吗?如果是这样(如果任何单独的段落直接适用),定义这种行为的标准措辞是什么?

你几乎是对的。这种行为实际上特别来自函数调用,而不是因为任何类型的"只工作一次"规则。

以下是终身延长"功能"的措辞,相关规则用粗体强调:

[C++11: 12.2/5]:[..]引用绑定到的临时对象或作为引用绑定到子对象的完整对象的临时对象在引用的生存期内持续存在除外:

  • [..]
  • 函数调用(5.2.2)中与引用参数的临时绑定将持续存在,直到包含该调用的完整表达式完成为止
  • [..]

这是两个问题报告的主题,http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299和http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1568。

我是前一期报告的记者,该报告旨在涵盖所有这些引用绑定到临时对象的情况,但不打算延长其使用寿命。问题正文中的描述只提到prvalues与临时表达式混淆(这些表达式实际上决定了它们评估对象的生存期是否延长)。但是lvalue和xvalues同样与标准中的混淆。在static_cast的上下文中发生这种情况的一个例子是问题编号#1568(其中"临时变量"的使用进一步混淆了问题)。

事实上,这个:

函数调用(5.2.2)中引用参数的临时绑定将持续存在,直到包含该调用的完整表达式完成为止。

与同一段落中的其他规则相矛盾。因为临时绑定到函数调用中的引用参数和本地自动引用变量。

这里适用的规则是常识。标准是措辞拙劣,事实上确实保证了这一点。但是没有实现它的实用方法。

可能我有点慢,但对我来说,阅读其他答案并不能清楚这个问题的解决方案。因此,我修改了显示的代码,并希望为其他人总结:答案是,如果访问y,您将得到未定义的行为

运行此代码:

struct foo {
    int id;
    foo(int id) : id(id) { std::cout << "ctor " << id << std::endl; };
    ~foo() { std::cout << "dtor " << id << std::endl; }
};
const foo& func(const foo& a, const foo&) { return a; }
int main(int argc, char** argv) {
    foo x(1);
    const foo& y = func(foo(2), x);
    std::cout << "main " << y.id << std::endl;
    return 0;
}

我的输出是:

ctor 1
ctor 2
dtor 2
main 2
dtor 1

但是线main 2未定义的行为

相关文章: