Использование «new» с initializer_list не присваивает строковые значения, в то время как значения int работают - PullRequest
2 голосов
/ 01 апреля 2020

Работает, когда я создаю переменную с std::initializer_list<std::string>:

auto a = std::initializer_list<std::string>{"1", "2", "3", "4"};

enter image description here

Но когда я создаю переменную с a указатель до std::initializer_list<std::string>, значения указателя пусты:

auto b = new std::initializer_list<std::string>{"1", "2", "3", "4"};

enter image description here

Я пытался с целочисленными значениями, и оба случая работают (std::initializer_list<int>{1, 2, 3, 4} и new std::initializer_list<int>{1, 2, 3, 4}).

Ответы [ 2 ]

2 голосов
/ 01 апреля 2020

В стандарте (C ++ 17) говорится, ссылаясь на массив const std::string, который поддерживает initializer_list:

Массив имеет то же время жизни, что и любой другой временный объект за исключением того, что инициализация объекта списка инициализатора из массива продлевает время жизни массива точно так же, как привязка ссылки к временному объекту.

В вашем коде динамически размещенный объект списка инициализатора инициализируется с помощью массив, так что этот текст применяется.

Правила продления времени жизни для привязки ссылки к временному внутри нового инициализатора : (C ++ 17 [class.teven] /6.3)

Временная привязка к ссылке в new-initializer сохраняется до завершения полного выражения, содержащего new-initializer . [Пример:

struct S { int mi; const std::pair<int,int>& mp; };
S a { 1, {2,3} };
S* p = new S{ 1, {2,3} }; // Creates dangling reference

Таким образом, кажется, что резервный массив уничтожается в конце строки, содержащей new, поэтому попытка проверить его после этого приведет к неопределенному поведению (то есть вы можете или может не увидеть, что вы ожидаете).

0 голосов
/ 01 апреля 2020

Итак, я написал полный пример:

#include <iostream>
#include <string>

void print(std::initializer_list<std::string> &il)
{
    for (auto &s: il) std::cout << s << ' ';
    std::cout << std::endl;
}

int main( void ) {
    auto a = std::initializer_list<std::string>{"1", "2", "3", "4"};
    auto b = new std::initializer_list<std::string>{"5", "6", "7", "8"};

    print (a);
    print (*b);
}

И компилятор сказал мне, что случилось:

$ clang++ std=c++17 so.cpp
so.cpp:12:49: warning: array backing the allocated initializer list will be destroyed at the end of the full-expression
      [-Wdangling-initializer-list]
        auto b = new std::initializer_list<std::string>{"5", "6", "7", "8"};
                                                       ^~~~~~~~~~~~~~~~~~~~
1 warning generated.
...