Почему этот initializer_list использует неправильно себя при передаче строк? - PullRequest
9 голосов
/ 09 апреля 2011

Я пробовал реализацию списка инициализаторов C ++ 0x моей версии G ++, но она выводит только пустые строки.

#include <initializer_list>
#include <iostream>
#include <string>

int main() {
  std::initializer_list<std::string> a({"hello", "stackoverflow"});
  for(auto it = a.begin(), ite = a.end(); it != ite; ++it)
    std::cout << *it << std::endl;
}

Понятия не имею, что я сделал не так. Кто-нибудь может мне помочь, пожалуйста?

Ответы [ 2 ]

3 голосов
/ 09 апреля 2011

Похоже, вы создаете два списка инициализатора в примере выше. Временные {"hello", "stackoverflow"} и std::initializer_list<std::string> a.

В gcc списки инициализаторов {} на самом деле являются временными массивами, время жизни которых заканчивается после полного оператора (если только они не связаны напрямую с std::initializer_list, как в строке комментария в примере ниже).

Время жизни внутреннего массива первого списка заканчивается сразу после того, как возвращается конструктор a, и поэтому массив a теперь указывает на недопустимую память (gcc только копирует указатель). Вы можете проверить, что деструкторы std::string вызываются до входа в цикл.

И когда вы зацикливаетесь, вы читаете неверную память.

Согласно последнему стандартному черновику (n3242), §18.9 / 1, списки инициализатора не могут быть даже скопированы таким образом (они не предоставляют конструктора с параметрами).

#include <initializer_list>
#include <iostream>

class A
{
public:
  A(int)
  { }

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

int main()
{
  std::initializer_list<A> a({A(2), A(3)});
  // vs std::initializer_list<A> a{A(2), A(3)};
  std::cout << "after a's construction" << std::endl;
}

С gcc 4.5.0 я получаю

dtor
dtor
after a's construction
1 голос
/ 09 апреля 2011
std::initializer_list<std::string> a({"hello", "stackoverflow"});

Если я объявлю это как:

std::initializer_list<std::string> a{"hello", "stackoverflow"}; //without ()

, то это будет работать: http://ideone.com/21mvL

Но это странно.Похоже, это ошибка компилятора.


РЕДАКТИРОВАТЬ:

Это, безусловно, ошибка компилятора, потому что если я пишу (*it).c_str(), он печатает строки !!

std::initializer_list<std::string> a({"hello", "stackoverflow"}); //with ()
for(auto it = a.begin(), ite = a.end(); it != ite; ++it)
   std::cout << (*it).c_str() << std::endl;

Код: http://ideone.com/hXr7V

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...