C++14 中 std::intializer_list 对象的预期寿命是多少?

What is expected lifetime of std::intializer_list object in C++14?

请考虑这个简化的 程序:

#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 在作用域结束时被破坏。

Clang 打印:

A() ~A() . 

在建造的那一行摧毁std::initializer_list

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

很微妙。

A std::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()};

... 在两个编译器上生成 same output

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

根据cppreference

Until the resolution of CWG issue 1696, a temporary is permitted to bound to a reference member in a constructor initializer list, and it persists only until the constructor exits, not as long as the object exists. Such initialization is ill-formed since CWG 1696, although many compilers still support it (a notable exception is clang).