Почему я могу повторно инициализировать константу внутри цикла?
Компилятор не выдает никаких предупреждений или ошибок для следующего кода. Является ли значение const-определителя оскорбительным? Очевидно, что я не могу переназначить его позже в той же итерации цикла, но он, похоже, переназначает его после каждой итерации.
Образец кода:
for(int i = 0; i < 10; ++i)
{
const int constant = i;
}
4 ответа
Вы не реинициализируете его, вы просто инициализируете его в каждой итерации цикла *. Формально есть новый int
создаваться и уничтожаться в каждой итерации цикла, хотя компилятор может делать все, что захочет, если только он себя так ведет.
* Вы не можете действительно "повторно инициализировать" вещи в C++, инициализация происходит только один раз за время существования объекта
Если следовать Стандарту С, то (6.2.4 Длительность хранения объектов)
1 У объекта есть срок хранения, который определяет его время жизни. Существует четыре длительности хранения: статическое, потоковое, автоматическое и выделенное. Выделенное хранилище описано в 7.22.3.
а также
5 Объект, идентификатор которого объявлен без привязки и без статического спецификатора класса хранения, имеет автоматическую продолжительность хранения, как и некоторые составные литералы. Результат попытки косвенного доступа к объекту с автоматической продолжительностью хранения из потока, отличного от того, с которым связан объект, определяется реализацией.
6 Для такого объекта, у которого нет типа массива переменной длины, его время жизни простирается от входа в блок, с которым он связан, до тех пор, пока выполнение этого блока не закончится каким-либо образом. (Ввод закрытого блока или вызов функции приостанавливает, но не завершает выполнение текущего блока.) Если блок вводится рекурсивно, каждый раз создается новый экземпляр объекта. Начальное значение объекта не определено. Если для объекта указана инициализация, она выполняется каждый раз, когда в ходе выполнения блока достигается объявление или составной литерал; в противном случае значение становится неопределенным при каждом достижении декларации
И наконец (6.8.5 Итерационные операторы)
5 Оператор итерации - это блок, область действия которого является строгим подмножеством области действия включающего его блока. Тело цикла также является блоком, область действия которого является строгим подмножеством области действия оператора итерации.
Таким образом, в этом заявлении цикла
for(int i = 0; i < 10; ++i)
{
const int constant = i;
}
тело цикла является блоком. Переменная constant
имеет автоматическую продолжительность хранения. Новый экземпляр переменной создается каждый раз, когда блок выполняется рекурсивно.
В C++ вы можете добавить спецификатор класса хранения static
, В этом случае переменная действительно будет инициализирована только один раз, потому что она имеет статическую продолжительность хранения (в C вы не можете делать то же самое, потому что переменная должна быть инициализирована с помощью константного выражения).
Вот демонстрационная программа
#include <iostream>
int main()
{
for ( int i = 0; i < 10; ++i )
{
static const int constant = i;
std::cout << "constant = " << constant << std::endl;
}
return 0;
}
Его вывод
constant = 0
constant = 0
constant = 0
constant = 0
constant = 0
constant = 0
constant = 0
constant = 0
constant = 0
constant = 0
Вы на самом деле не реинициализируете здесь. Вы создаете новую переменную каждый раз через цикл.
constant
является локальным для блока внутри цикла. Когда блок заканчивается на данной итерации и управление возвращается к for
, constant
выходит за рамки и, следовательно, больше не существует. Когда for
начинает следующую итерацию цикла, новый экземпляр constant
создан и инициализирован.
Эта переменная инициализируется и уничтожается на каждой итерации, потому что она локальна для цикла.