[英]How would auto&& extend the life-time of the temporary object?
The code below illustrated my concern: 下面的代码说明了我的担忧:
#include <iostream>
struct O
{
~O()
{
std::cout << "~O()\n";
}
};
struct wrapper
{
O const& val;
~wrapper()
{
std::cout << "~wrapper()\n";
}
};
struct wrapperEx // with explicit ctor
{
O const& val;
explicit wrapperEx(O const& val)
: val(val)
{}
~wrapperEx()
{
std::cout << "~wrapperEx()\n";
}
};
template<class T>
T&& f(T&& t)
{
return std::forward<T>(t);
}
int main()
{
std::cout << "case 1-----------\n";
{
auto&& a = wrapper{O()};
std::cout << "end-scope\n";
}
std::cout << "case 2-----------\n";
{
auto a = wrapper{O()};
std::cout << "end-scope\n";
}
std::cout << "case 3-----------\n";
{
auto&& a = wrapper{f(O())};
std::cout << "end-scope\n";
}
std::cout << "case Ex-----------\n";
{
auto&& a = wrapperEx{O()};
std::cout << "end-scope\n";
}
return 0;
}
It's said that auto&&
will extend the life-time of the temporary object, but I can't find the standard words on this rule, at least not in N3690. 据说auto&&
会延长临时对象的寿命,但我找不到此规则的标准字词,至少在N3690中找不到。
The most relevant may be section 12.2.5 about temporary object, but not exactly what I'm looking for. 最相关的可能是关于临时对象的12.2.5节,但不完全是我要寻找的对象。
So, would auto&& life-time extension rule apply to all the temporary objects involved in the expression, or only the final result? 那么,auto &&生命周期扩展规则是适用于表达式中涉及的所有临时对象还是仅适用于最终结果?
More specific, is a.val
guaranteed to be valid (non-dangling) before we reach the end-of-scope in case 1? 更具体地说,在情况1到达作用域末端之前, a.val
保证有效(非悬挂)?
Edit: I updated the example to show more cases (3 & Ex). 编辑:我更新了示例以显示更多案例(3和Ex)。
You'll see that only in case 1 the lifetime of O is extended. 您将看到只有在情况1中,O的寿命才会延长。
In the same way that a reference to const
does: 引用const
方式相同:
const auto& a = wrapper{O()};
or 要么
const wrapper& a = wrapper{O()};
or also 或者也
wrapper&& a = wrapper{O()};
More specific, is
a.val
guaranteed to be valid (non-dangling) before we reach the end-of-scope in case 1? 更具体地说,在情况1到达作用域末端之前,a.val
保证有效(非悬挂)?
Yes, it is. 是的。
There's (almost) nothing particularly important about auto
here. 这里的auto
几乎没有什么特别重要的。 It's just a place holder for the correct type ( wrapper
) which is deduced by the compiler. 它只是由编译器推断出的正确类型( wrapper
)的占位符 。 The main point is the fact that the temporary is bound to a reference. 要点是,临时对象绑定到引用。
For more details see A Candidate For the “Most Important const” which I quote: 有关更多详细信息,请参见我引用的“最重要const”候选人 :
Normally, a temporary object lasts only until the end of the full expression in which it appears. 通常,临时对象仅持续到其出现的完整表达式的结尾。 However, C++ deliberately specifies that binding a temporary object to a reference to const on the stack lengthens the lifetime of the temporary to the lifetime of the reference itself 但是,C ++故意指定将临时对象绑定到堆栈上const的引用会延长临时对象的寿命至引用本身的寿命
The article is about C++ 03 but the argument is still valid: a temporary can be bound to a reference to const
(but not to a reference to non- const
). 本文是关于C ++ 03的,但该参数仍然有效:可以将临时绑定到对const
的引用(但不能绑定到对non- const
的引用)。 In C++ 11, a temporary can also be bound to an rvalue reference. 在C ++ 11中,临时变量也可以绑定到右值引用。 In both cases, the lifetime of the temporary is extended to the lifetime of the reference. 在这两种情况下,临时项的寿命都延长到参考的寿命。
The relevant parts of the C++11 Standard are exactly those referred in the OP, that is, 12.2 p4 and p5: C ++ 11标准的相关部分正是OP中提到的部分,即12.2 p4和p5:
4 - There are two contexts in which temporaries are destroyed at a different point than the end of the full expression. 4-在两种情况下,临时变量在与完整表达式末尾不同的位置被销毁。 The first context is [...] 第一个上下文是[...]
5 - The second context is when a reference is bound to a temporary. 5-第二种情况是引用绑定到临时项时。 [...] [...]
(There are some exceptions in the bullet points following these lines.) (这些行后面的项目符号中有一些例外。)
Update : (Following texasbruce's comment.) 更新 :(根据texasbruce的评论。)
The reason why the O
in case 2 has a short lifespan is that we have auto a = wrapper{O()};
情况2中的O
寿命短的原因是我们有auto a = wrapper{O()};
(see, there's no &
here) and then the temporary is not bound to a reference. (请参见,此处没有&
),然后该临时对象就不会绑定到引用。 The temporary is, actually, copied into a
using the compiler generated copy-constructor. 实际上,临时文件是使用编译器生成的copy-constructor复制到a
。 Therefore, the temporary doesn't have its lifetime expanded and dies at the end of the full expression in which it appears. 因此,临时项不会延长其生存期,并且会在出现的完整表达式的末尾死亡。
There's a danger in this particular example because wrapper::val
is a reference. 在此特定示例中存在危险,因为wrapper::val
是引用。 The compiler generated copy-constructor of wrapper
will bind a.val
to the same object that the temporary's val
member is bound to. 编译器生成的wrapper
copy-constructor会将a.val
绑定到与临时val
成员绑定到的同一对象。 This object is also a temporary but of type O
. 该对象也是临时的,但类型为O
Then, when this latter temporary dies we see ~O()
on the screen and a.val
dangles! 然后,当后一个临时对象死亡时,我们在屏幕上看到a.val
~O()
,并且a.val
悬挂了!
Contrast case 2 with this: 与此进行对比的情况2:
std::cout << "case 3-----------\n";
{
O o;
auto a = wrapper{o};
std::cout << "end-scope\n";
}
The output is (when compiled with gcc using option -fno-elide-constructors
) 输出是(当使用gcc使用选项-fno-elide-constructors
编译时)
case 3-----------
~wrapper()
end-scope
~wrapper()
~O()
Now the temporary wrapper
has its val
member bound to o
. 现在,临时wrapper
将其val
成员绑定到o
。 Notice that o
is not a temporary. 请注意, o
不是临时的。 As I said, a
is a copy of the wrapper
temporary and a.val
also binds to o
. 如我所说, a
是wrapper
临时文件的副本,而a.val
也绑定到o
。 Before the scope ends the temporary wrapper
dies and we see the first ~wrapper()
on the screen. 在作用域结束之前,临时wrapper
死亡,我们在屏幕上看到第一个~wrapper()
。
Then the scope ends and we get end-scope
. 然后范围结束,我们得到end-scope
。 Now, a
and o
must be destroyed in the reverse order of construction, hence we see ~wrapper()
when a
dies and finally ~O()
when it's o
's time. 现在, a
和o
必须在施工相反的顺序被破坏,因此,我们看到~wrapper()
时, a
模具和最后~O()
时,它的o
的时间。 This shows that a.val
doesn't dangle. 这表明a.val
不会a.val
。
(Final remark: I've used -fno-elide-constructors
to prevent a optimization related to copy-construction that would complicate the discussion here but this is another story .) (最后再说一句:我已经使用-fno-elide-constructors
,防止复制建设,将这里的讨论复杂化相关的一个优化但这是另一个故事 。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.