首页 > 解决方案 > C++14 中 std::initializer_list 对象的预期生命周期是多少?

问题描述

请考虑这个简化的程序:

#include <iostream>

struct A
{
    A() { std::cout << "A() "; }
    ~A() { std::cout << "~A() "; }
};

int main()
{
    auto l = std::initializer_list<A>{A()};
    std::cout << ". ";
}

https://gcc.godbolt.org/z/1GWvGfxne

GCC在这里打印

A() . ~A()

这意味着std::initializer_list在范围结束时被破坏。

铿锵印:

A() ~A() . 

在它被建造的那条线上摧毁std::initializer_list

两个编译器在这里的行为是否正确,或者其中一个是错误的?

标签: c++c++14language-lawyerinitializer-listobject-lifetime

解决方案


这是微妙的。

Astd::initializer_list由底层数组(由编译器生成)支持。这个数组就像一个临时对象,std::initializer_list是一种绑定到它的引用类型。因此,只要“引用”存在,它将延长临时数组的生命周期。

在 C++14 中,我们不保证复制省略。所以应该发生的是好像std::initializer_list<A>{A()}产生了一个临时的,将另一个临时initializer_list数组绑定到它,并将临时复制到.initializer_listl

std::initializer_list就生命周期延长而言,其行为类似于常规引用。只有原始引用延长了生命周期,而我们的原始引用本身是临时的。因此,底层数组在包含l. Clang 是正确的。

直接初始化...

std::initializer_list<A> l {A()};

...在两个编译器上产生相同的输出。

同时,为 C++17 编译时,您的原始代码在 GCC 和 Clang 上的行为相同。


推荐阅读