繁体   English   中英

临时对象的生命周期延长:包含函数调用的完整表达式是什么?

[英]Lifetime extension of temporary objects: what is the full expression containing a function call?

介绍

假设有一个Container类存储Widget对象。 有一个迭代器类负责导航这样的容器。 这个迭代器类( MyIterator )在其构造函数中接受一个对Stuff向量的常量引用,它需要迭代容器中的正确元素。 代码可能如下所示:

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;
};

问题

我很好奇rvalue与 const 引用的绑定,以及生命周期扩展如何工作。

虽然vec可以绑定到临时rvalue ,但一旦rvalue的生命周期结束,这将导致stuffVector成为悬空引用。 所以像这样旨在为对象myContainer创建迭代器的代码是错误的:

MyIterator it = {myContainer, {stuff1, stuff2, stuff3}};
// Here it.stuffVector is a dangling reference!

阅读cppreference中临时对象的生命周期延长我发现:

每当引用绑定到临时对象或其子对象时,临时对象的生命周期就会延长以匹配引用的生命周期(...)此生命周期规则有以下例外:(...)

  • 函数调用中引用参数的临时绑定一直存在,直到包含该函数调用的完整表达式结束:如果函数返回一个引用,该引用比完整表达式的寿命长,则它成为一个悬空引用。

问题

突出显示的部分让我想到了这个问题:这段代码能否成功获得myContainer内容的过滤版本?

std::vector<Widget> filteredWidgets;
std::copy_if (
    MyIterator{myContainer, {stuff1, stuff2, stuff3}},
    MyContainer.end(),
    std::back_inserter(filteredWidgets),
    [&](Widget w) { return ...; });

第二个参数是rvalue ,因此存在创建悬空引用的危险,但我对文档的理解是rvalue的生命周期将延长到std::copy_if结束,所以没问题。 哪一个?

注意:我知道问题和设计,如前所述,可能看起来有点奇怪,但它的灵感来自我在野外发现的真实代码。 我对延长寿命的限制感兴趣,而不是想出不同的设计,这会使问题变得无关紧要。

是的,整个std::copy_if调用是完整的表达式,临时的std::vector<Stuff>只会在调用返回后被销毁。

这与按值函数参数不同。 如果构造函数采用std::vector<Stuff>而不是const std::vector<Stuff>& ,那么当构造函数返回时,对象是存活那么久还是立即销毁将由实现定义。


完整表达式是[intro.execution]/5中列出的表达式之一。 任何特定情况(例如未评估的操作数、立即调用等)都不适用于此处,因此不适用,相关条件是:

一个表达式,它不是另一个表达式的子表达式,也不是完整表达式的一部分。

copy_if调用表达式是该语句中唯一适用的(在 lambda 主体之外)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM