[英]Lifetime extension of temporary objects: what is the full expression containing a function call?
Say there is a Container
class which stores Widget
objects.假设有一个
Container
类存储Widget
对象。 There is an iterator class in charge of navigating such container.有一个迭代器类负责导航这样的容器。 This iterator class (
MyIterator
) takes a const-reference to a vector of Stuff
in its constructor, which it needs to iterate over the right elements in the container.这个迭代器类(
MyIterator
)在其构造函数中接受一个对Stuff
向量的常量引用,它需要迭代容器中的正确元素。 The code may look like this:代码可能如下所示:
class MyIterator
{
public:
MyIterator(
const Container& container, // Container to be navigated
const std::vector<Stuff>& vec) // Parameter which controls the behaviour of the iteration
: container(container)
, stuffVector(vec)
{}
...
private:
const Container& container;
const std::vector<Stuff>& stuffVector;
};
I'm curious about the binding of rvalue s to const references, and how the lifetime extensions work.我很好奇rvalue与 const 引用的绑定,以及生命周期扩展如何工作。
While vec
can be bound to a temporary rvalue , that will cause stuffVector
to be a dangling reference once the rvalue 's lifetime is over.虽然
vec
可以绑定到临时rvalue ,但一旦rvalue的生命周期结束,这将导致stuffVector
成为悬空引用。 So code like this, aimed to create an iterator for object myContainer
is wrong:所以像这样旨在为对象
myContainer
创建迭代器的代码是错误的:
MyIterator it = {myContainer, {stuff1, stuff2, stuff3}};
// Here it.stuffVector is a dangling reference!
Reading up on lifetime extension of temporary objects in cppreference I found:阅读cppreference中临时对象的生命周期延长我发现:
Whenever a reference is bound to a temporary object or to a subobject thereof, the lifetime of the temporary object is extended to match the lifetime of the reference (...) There are following exceptions to this lifetime rule: (...)
每当引用绑定到临时对象或其子对象时,临时对象的生命周期就会延长以匹配引用的生命周期(...)此生命周期规则有以下例外:(...)
- a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call : if the function returns a reference, which outlives the full expression, it becomes a dangling reference.
函数调用中引用参数的临时绑定一直存在,直到包含该函数调用的完整表达式结束:如果函数返回一个引用,该引用比完整表达式的寿命长,则它成为一个悬空引用。
The highlighted part leads me to this question: would this piece of code succeed in getting a filtered version of the contents of myContainer
?突出显示的部分让我想到了这个问题:这段代码能否成功获得
myContainer
内容的过滤版本?
std::vector<Widget> filteredWidgets;
std::copy_if (
MyIterator{myContainer, {stuff1, stuff2, stuff3}},
MyContainer.end(),
std::back_inserter(filteredWidgets),
[&](Widget w) { return ...; });
The second argument is an rvalue , so there is the danger of creating a dangling reference, but my understanding of the documentation is that the rvalue 's lifetime will be extended untill the end of std::copy_if
, so it would be fine.第二个参数是rvalue ,因此存在创建悬空引用的危险,但我对文档的理解是rvalue的生命周期将延长到
std::copy_if
结束,所以没问题。 Which one is it?哪一个?
NOTE: I am aware the problem and the design, as stated, might seem a bit strange, but it's inspired in real code I've found in the wild.注意:我知道问题和设计,如前所述,可能看起来有点奇怪,但它的灵感来自我在野外发现的真实代码。 I'm interested in the limits of the lifetime extension, not so much in coming up with different designs which would make the question irrelevant.
我对延长寿命的限制感兴趣,而不是想出不同的设计,这会使问题变得无关紧要。
Yes, the whole std::copy_if
call is the full-expression and the temporary std::vector<Stuff>
will be destroyed only after the call returns.是的,整个
std::copy_if
调用是完整的表达式,临时的std::vector<Stuff>
只会在调用返回后被销毁。
This is different from by-value function parameters.这与按值函数参数不同。 If the constructor took a
std::vector<Stuff>
instead of a const std::vector<Stuff>&
, then it would be implementation-defined whether the object lives that long or is destroyed immediately when the constructor returns.如果构造函数采用
std::vector<Stuff>
而不是const std::vector<Stuff>&
,那么当构造函数返回时,对象是存活那么久还是立即销毁将由实现定义。
A full-expression is one of the expressions listed in [intro.execution]/5 .完整表达式是[intro.execution]/5中列出的表达式之一。 None of the specific cases (such as unevaluated operands, immediate invocations, etc.) apply here and so falling through, the relevant condition is:
任何特定情况(例如未评估的操作数、立即调用等)都不适用于此处,因此不适用,相关条件是:
an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression.
一个表达式,它不是另一个表达式的子表达式,也不是完整表达式的一部分。
The copy_if
call expression is the only one in that statement to which this applies (outside of the lambda body). copy_if
调用表达式是该语句中唯一适用的(在 lambda 主体之外)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.