从变量初始化std :: initializer_list

时间:2017-12-20 14:39:34

标签: c++ c++11

class L {
      public:
        L(const std::string& name, std::initializer_list<long long int> dims, float* data);
        std::string name;
        std::initializer_list<long long int> dims;
        float* data;
    };

我可以关注

vector<L> input = {
                {"aaaaa", {1, 20, 1400, 1}, input_data}};

但是我不能跟随它(它编译,但运行会崩溃)

long long int a =20;
vector<L> input = {
                {"aaaaa", {1, a, 1400, 1}, input_data}};

1 个答案:

答案 0 :(得分:2)

std::initializer_list不是容器。它是对临时数组的引用。它是目的用于初始化另一个对象的类型(因此称为初始化程序 _list),并且不应将其用于除之外的任何 这一点。

initializer_list引用的临时数组与C ++中的任何其他临时数组一样。在

的情况下
vector<L> input = {
    {"aaaaa", {1, 20, 1400, 1}, input_data}};

执行此语句后,临时数组将立即销毁。因此,您将存储指向已销毁数组的指针。因此,您的计划有UB。

现在,如果使用变量,为什么你的UB只会导致崩溃?

那是因为“临时数组”意味着编译器想要的意思。在{1, 20, 1400, 1}的情况下,这些都是文字。因此,编译器可以将该数组放在二进制文件中的静态存储中,而不是在运行时将其作为堆栈数组。这节省了运行时堆栈空间,因此可以认为是合理的优化。

但是,一旦在braced-init-list中使用变量,就无法工作(除非它是constexpr变量)。因此编译器需要更严格地遵循临时措辞。因此,它创建一个堆栈数组,在该代码执行后回收。因此,当您稍后访问它时......繁荣。

即便如此,也不依赖于此。你的程序有UB。