Хорошо, я хочу знать, почему этот код работает, я только что понял, что у меня есть две переменные с одинаковым именем в одной и той же области видимости.
Вы, кажется, смущены областями видимости. Они не "в одной и той же" области видимости ... цикл for имеет свою собственную вложенную / внутреннюю область видимости. Что еще более важно, чтобы понять, почему язык это позволяет, подумайте:
#define DO_SOMETHING \
do { for (int i = 1; i <= 2; ++i) std::cout << i << '\n'; } while (false)
void f()
{
for (int i = 1; i <= 10; ++i)
DO_SOMETHING();
}
Здесь текст, замененный макросом "DO_SOMETHING", оценивается в той же области, что и i. Если вы пишете DO_SOMETHING, вам может потребоваться его расширение для хранения чего-либо в переменной и определения идентификатора i
- очевидно, у вас нет возможности узнать, существует ли оно уже в вызывающем контексте. Вы можете попытаться выбрать что-то более неясное, но у вас будут люди, использующие такие запутанные имена переменных, что их поддержка кода пострадает, и независимо от того, рано или поздно произойдет столкновение. Таким образом, язык позволяет внутренним областям вводить переменные с одинаковыми именами: самое внутреннее совпадение используется до тех пор, пока не выйдет его область действия.
Даже когда вы не имеете дело с макросами, очень сложно остановиться и подумать о том, использует ли какой-либо внешний вид уже то же имя. Если вы знаете, что вам нужна просто быстрая операция, вы можете выдать ей независимую (вложенную) область без учета этого более широкого контекста (если у вас нет кода, который действительно хочет использовать переменную external-scope: если вы это делаете тогда вы можете иногда указывать его явно (если он ограничен пространствами имен и классами, но если он находится в теле функции, вам в конечном итоге потребуется изменить имя своей собственной переменной цикла (или создать ссылку или что-то на нее, прежде чем вводить одноименное имя) переменная)).