在类中存储的闭包中通过引用捕获的临时的生命周期

时间:2018-01-01 19:24:11

标签: c++ language-lawyer c++17 lifetime temporary-objects

请考虑以下代码段:

struct foo { };

template <typename F>
struct impl : F
{
    impl(F&& f) : F{std::move(f)} { }
    auto get() { return (*this)(); }
};

template <typename X>
auto returner(X&& x)
{
    return impl{[&x]{ return x; }};
//               ^~
}

int main()
{
    auto x = returner(foo{}).get();
}

live example on wandbox.org

  • 是否保证foo{}returner(foo{}).get()表达式的整个持续时间内都有效?

  • foo{}仅为returner(foo{})生存,因此在调用impl::get()时会导致未定义的行为

标准在[class.temporary]中说:

  

临时对象在评估完整表达式的最后一步时被销毁()包含创建它们的点。

[intro.execution]

  

完整表达是

     
      
  • 未评估的操作数,

  •   
  • 一个常量表达式,

  •   
  • init-declarator或mem-initializer,包括初始化程序的组成表达式,

  •   
  • 调用在临时对象([class.temporary])以外的对象的生命周期结束时生成的析构函数,或

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

  •   

我不确定与foo{}相关的完整表达returner(foo{})还是returner(foo{}).get()

1 个答案:

答案 0 :(得分:10)

这里重要的部分是:

  

完整表达式是一个表达式,它不是另一个表达式的子表达式,而不是完整表达式的一部分。< / p>

因此,在returner(foo{}).get()中,returner(foo{})是表达式returner(foo{}).get()的子表达式,因此它不是完整表达式。因此:

  

是否保证在foo{}表达的整个过程中returner(foo{}).get()都会存活?