20

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

#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 << "main\n";
}

输出

destroying!
main
destroying!

它似乎表明foo临时的生命周期没有扩展到整个main,即使它被绑定到const该范围内的 ref-to- 。

那么,可以推测,延长寿命只能“工作一次”;也就是说,它在func' 的参数被初始化时应用,但不通过连续绑定传递。

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

4

4 回答 4

9

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

这是整个生命周期延长“功能”的措辞,相关规则以粗体强调:

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

  • [..]
  • 临时绑定到函数调用 (5.2.2) 中的引用参数将持续存在,直到包含调用的完整表达式完成。
  • [..]
于 2013-02-06T17:53:56.087 回答
7

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

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

其实这个:

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

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

于 2013-02-06T21:12:13.450 回答
3

这里适用的规则是常识。该标准措辞不佳,实际上确实保证了这一点。但是没有实用的方法来实现它。

于 2013-02-06T17:58:09.900 回答
1

可能我有点慢,但对我来说,通过阅读其他答案并不清楚这个问题的解决方案是什么。因此我修改了显示的代码并想为其他人总结一下:答案是,如果你访问,你会得到未定义的行为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未定义的行为

于 2015-11-29T18:09:28.193 回答