2013-07-08 4 views
10

У меня есть повреждение памяти в этом коде: выходПовреждение памяти с станд :: initializer_list

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

int main() { 
    std::vector<std::initializer_list<std::string>> lists = { 
     { 
      {"text1"}, 
      {"text2"}, 
      {"text3"} 
     }, 
     { 
      {"text4"}, 
      {"text5"} 
     } 
    }; 

    int i = 0; 
    std::cout << "lists.size() = " << lists.size() << std::endl; 
    for (auto& list: lists) { 
     std::cout << "lists[" << i << "].size() = " << lists[i].size() << std::endl; 
     int j = 0; 
     for (auto& string: list) { 
      std::cout << "lists[" << i << "][" << j << "] = "<< string << std::endl; 
      j++; 
     } 
     i++; 
    } 
} 

Пример:

lists.size() = 2 
lists[0].size() = 3 
lists[0][0] = text10�j ����text2H�j ����text3`�j ����text4����text5��������q 

Проблема в std::initializer_list. Изменение std::initializer_list до std::vector решает проблему.

Вопрос в том, почему коррупция памяти имеет место с std::initializer_list?

+26

'станд :: initializer_lists' имеют свое название по причине. Предполагается, что они используются только * для инициализации *, а не для длительного хранения. Вот почему они имеют ссылочную семантику. Все ваши 'std :: initializer_list' фактически живут до конца инициализации' lists'. – Xeo

+6

'^^' Этот комментарий был официально принят системой как правильный ответ на ваш вопрос. Спасибо, что воспользовались нашими услугами! –

ответ

1

Из-STD :: String объектов были разрушены до этой строки:

int i = 0;

Если станд :: строка имеет отладочный вывод в их деструкторов и ctors. Вы будете видеть что-то вроде: станда :: строки :: строка 5 раз, станда :: строки :: ~ строки 5 раз и после этого

lists.size() = 2

из-за initializre_list не содержат копию станд :: строковых объектов, они (временное станд :: строка objects0 только что создали и уничтожены до «;»

это, например, как ссылки на тейк StD :: строковый объект в таком выражении:

std :: cout < < std :: string ("17");

Но если вы замените std :: string на «const char *» в вашем примере, все должно работать, я полагаю.

1

для хранения списка инициализаторов уничтожаются после использования, что перед строкой:

int i = 0; 

Его деталь spesific реализации, но это, как правило, создает динамический массив при строительстве, и это динамический массив разрушается при разрушении.

Вы можете найти более подробную информацию на cppreference page