Почему записи этой карты STL не инициализируются в GCC 4.5.1? - PullRequest
7 голосов
/ 28 декабря 2011

Вот выдержка из кода.

std::map<double, double> temp;

temp[0] = .1;

cout << temp[1] << endl;
// result varies based on compiler

Я компилирую с использованием GCC версии 4.4.1 и получаю значение 0 из temp[1], как и ожидалось.Мой коллега компилирует на GCC версии 4.5.1.В режиме отладки (с флагом -g) он получает 1000.При компиляции режима релиза (флаг -O2) он получает 0.

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

Более того, Стандартная библиотека C ++ Джосуттиса утверждает, что

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

Почему элементы карты не инициализируются в GCC 4.5.1 в режиме отладки?Я не понимаю, что другие говорили об этом поведении правильно?Является ли построение по умолчанию новых элементов чем-то, что не обязательно является частью стандарта?Или это может быть реальной ошибкой в ​​компиляторе?

Ответы [ 3 ]

4 голосов
/ 28 декабря 2011

Он должен работать так, как вы говорите (print 0), и фактически в g ++ 4.5.2 он печатает 0 с -g, -O2 или обоими. Если он не печатает 0, то это почти наверняка ошибка библиотеки (или программа вашего коллеги уже имеет неопределенное поведение, и в этом случае все ставки отключены (TM)).

2 голосов
/ 28 декабря 2011

Да, он гарантированно будет инициализирован до 0 согласно стандарту C ++.

Ссылка:

Стандарт C ++ 03:

23.3.1.2 доступ к элементу карты [lib.map.access]

T& operator[](const key_type& x);

Returns:(*((insert(make_pair(x, T()))).first)).second.

T() default-инициализирует объект.В то время как значения по умолчанию для переменных указаны в:

C ++ 03 Standard 8.5 / 5:

To default-initialize объект типа T означает:
- если T является типом класса, отличным от POD (раздел 9), вызывается конструктор по умолчанию для T (и инициализация является некорректной, если у T нет доступного конструктора по умолчанию));
- если T является типом массива, каждый элемент инициализируется по умолчанию;
- в противном случае объект инициализируется нулями.

Последний случай применяется кВаш код здесь.

1 голос
/ 28 декабря 2011

Как и следовало ожидать, фрагмент кода является упрощенной версией того, что действительно происходит.Оказывается, на карте используется команда поиска, поэтому по существу вызывается map.find(1)->second, а не просто map[1].Это объясняет неопределенное поведение.

...