#include <iostream>
struct A {
A();
const int& i;
};
A::A() : i(123) {}
int main() {
A a;
std::cout << a.i << std::endl;
}
и#include <iostream>
struct A {
A() : i(123) {}
const int& i;
};
int main() {
A a;
std::cout << a.i << std::endl;
}
Будучи скомпилированными компилятором от Sun или GCC, эти два примера печатают разные результаты. И первый - неправильный. Студия же 2010, с настройками по умолчанию, дает предупреждение и генерирует код, работающий правильно (точнее, как ожидает программист) в обоих случаях.
Понятно, что код сам по себе несколько странный, так как сложно представить себе, кому может понадобиться инициализировать ссылку константой, которая передается в конструктор не извне, а создается временно во время обработки списка инициализации. Но вот на ошибку-опечатку вполне себе потянет.
Ко мне пример попал как результат анализа реального бага.
gcc - unix-вариант? Или mingw?
ОтветитьУдалитьВ windows оба компилятора (и gcc, и студия) дали 123 во обоих примерах.
gcc 4.1.2, 4.4.5, 4.5.1 обработали нормально, правда ворнинга не дали.
ОтветитьУдалитьЯ пробовал на codepad.org. Там gcc под unix'ом.
ОтветитьУдалитьВ обоих случаях программа некорректна. Согласно стандарту, "A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits". (12.2p5) Это значит что как только A::A() завершается, ссылка начинает указывать на мусор.
ОтветитьУдалитьДалее всё зависит от того, где компилятор берёт память под временные знчения и как он потом её использует. Sun'овский компилятор, похоже, агрессивнее всего в повторной утилизации памяти. Остальные же позволяют старому значению посидеть в ней подольше.