【问题标题】:Can lifetime of objects in a initializer list be extended?初始化列表中对象的生命周期可以延长吗?
【发布时间】:2018-12-15 09:01:26
【问题描述】:

我的印象是std::initializer_list 可能表现得像 C++ 中的文字字符串,甚至进一步延长 const 引用的生命周期。这是正确的评价吗?

initializer_list 中的对象是否可以稍后在本地范围内以某种方式引用(不复制它们)?在全球范围内?

例如,这个测试在 GCC 和 clang 中通过。 这只是偶然吗?

#include<cassert>
#include<initializer_list> 
struct A{
    double const* p;
    A(std::initializer_list<double> il){ p = &*(il.begin() + 1); };
};
double f(){return 5.;}
int main(){
   A a1{1.,2.,3.};
   assert( *a1.p == 2. );
   A a2{1., f(), f()};
   assert( *a2.p == 5. );
}

【问题讨论】:

    标签: c++ c++11 lifetime initializer-list const-reference


    【解决方案1】:

    这是未定义的行为。

    在您的情况下,initializer_list 指的是临时数组const double[3],该数组的生命周期如下所述:

    ref 底层数组在生命周期后不保证存在 原始初始化列表对象已结束。 [直到 c++14]

    底层数组的生命周期与其他数组相同 临时对象 [c++14 起]

    ref 作为评估的最后一步,所有临时对象都被销毁 全表达

    所以在您的情况下,当调用A 的构造函数时,会创建具有 3 个双精度的临时数组,然后您将获取临时数组元素的地址,并且当构造函数结束时,临时数组被销毁(在这种情况下,完整的表达式是ctor 的调用),因此p 是悬空指针。

    【讨论】:

    • 谢谢。我不明白为什么这不能成为标准行为,尤其是在第一种情况下和 POD 类型中。 In 与char const* p = "hello"; assert(p[1] == 'e') 不会有太大不同。第二种情况比较棘手。
    猜你喜欢
    • 1970-01-01
    • 2016-12-25
    • 2020-09-05
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    相关资源
    最近更新 更多