Каждый раз, когда мы входим в цикл for
i
. Каждый раз, когда мы выходим из цикла for
, переменная i
уничтожается до того, как мы достигнем инструкции v.push_back(stripped);
.Обратите внимание на то, что компиляторы (и редакторы связей) — довольно разумны и способны оптимизировать код. В частности, компиляторы не выделяют и не освобождают память чаще, чем это действительно требуется.
8.6.1. Вычисление выражения
v[i] = ++i; // неопределенный порядок вычислений
v[++i] = i; // неопределенный порядок вычислений
int x = ++i + ++i; // неопределенный порядок вычислений
cout << ++i << ' ' << i << '\n'; // неопределенный порядок вычислений
f(++i,++i); // неопределенный порядок вычислений
К сожалению, не все компиляторы выдают предупреждение о таких ошибках; это плохо, потому что нельзя рассчитывать на то, что результаты будут одинаковыми при выполнении вычислений на другом компьютере, при использовании других компиляторов или при других установках оптимизатора.
Компиляторы действительно по-разному обрабатывают этот код; избегайте таких ситуаций.
Обратите внимание на то, что оператор =
v[++i] = i
имеет неопределенный результат.8.6.2. Глобальная инициализация
Глобальные переменные (и переменные из пространства имен; раздел 8.7) в отдельной единице трансляции инициализируются в том порядке, в котором они появляются. Рассмотрим пример.
// файл f1.cpp
int x1 = 1;
int y1 = x1+2; // переменная y1 становится равной 3
Эта инициализация логически происходит до выполнения кода в функции main
// файл f2.cpp
extern int y1;
int y2 = y1+2; // переменная y2 становится равной 2 или 5
Такой код нежелателен по нескольким причинам: в нем используются глобальные переменные, которые имеют слишком короткие имена, и сложная инициализация глобальных переменных. Если глобальные переменные в файле f1.cpp
f2.cpp
, то переменная y2
будет инициализирована числом 5
(как наивно ожидает программист).Однако, если глобальные переменные в файле f2.cpp
f1.cpp
, переменная y2
будет инициализирована числом 2
(поскольку память, используемая для глобальных переменных, инициализируется нулем до попытки сложной инициализации). Избегайте этого и старайтесь не использовать нетривиальную инициализацию глобальных переменных; любой инициализатор, отличающийся от константного выражения, следует считать сложным.Но что же делать, если нам действительно нужна глобальная переменная (или константа) со сложной инициализацией? Например, мы можем предусмотреть значение по умолчанию для переменных типа Date
const Date default_date(1970,1,1); // дата по умолчанию: 1 января 1970
Как узнать, что переменная default_date
const Date default_date // возвращает дату по умолчанию
{
return Date(1970,1,1);
}
Эта функция создает объект типа Date
default_date
. Часто этого вполне достаточно, но если функция default_date
вызывается часто, а создание объекта класса Date связано с большими затратами, предпочтительнее было бы конструировать его только один раз. В таком случае код мог бы выглядеть так: