Это неопределенное поведение, чтобы переопределить переменную в закрытой области видимости? - PullRequest
0 голосов
/ 16 октября 2018
#include <iostream>
using namespace std;

int main() {
    int i = 0;
    if(true) {
        int i = 5;
        cout << i << '\n';
    }
    return 0;
}

Попытался запустить приведенный выше код на Ideone, чтобы убедиться, что он разрешен.Результаты меня сбивают с толку:

  • У нас есть ошибка компиляции (1) , (2)
  • Или этот код печатает 5 как и ожидалось (1)
  • Или ничего не печатается (1) , (2)

Как вы можете видеть из моих ссылок, этот код работает по-разному каждый раз, когда компилируется в Ideone!Это пахнет неопределенным поведением (UB).

OK C ++ известен своими не интуитивными поведениями, НО!- Я признаю, что это просто моя интуиция, но я не ожидаю, что даже C ++ сделает переопределение переменной во внутренней области видимости UB!Я ожидал бы либо затенения, либо обязательной ошибки компиляции.

Является ли мой код действительно UB в соответствии со стандартом C ++, или это просто особенность Ideone и / или gcc?Если это UB, это UB, потому что я объявил i или по какой-то другой причине, которую я сейчас не замечаю?

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Нет неопределенного поведения, стандарт допускает скрытие имени , оно покрыто [basic.scope.hiding] :

Объявлениеимя во вложенной декларативной области скрывает декларацию с тем же именем во вложенной декларативной области;см. [basic.scope.declarative] и [basic.lookup.unqual].

и [basic.scope.declarative] говорит:

Каждое имя вводится в некоторой части текста программы, называемой декларативной областью, которая является самой большой частью программы, в которой это имя является действительным, то есть в котором это имя может использоваться в качестве неквалифицированного имени для ссылки на то же самоеюридическое лицо.В общем, каждое конкретное имя действительно только в некоторой, возможно, непрерывной части текста программы, называемой областью действия.Чтобы определить область декларации, иногда удобно обратиться к потенциальной области декларации.Область объявления совпадает с ее потенциальной областью, если только потенциальная область не содержит другую декларацию с тем же именем.В этом случае потенциальная область действия объявления во внутренней (содержащейся) декларативной области исключается из области действия декларации во внешней (содержащей) декларативной области.

и дает следующий пример:

[Пример: в

int j = 24;
int main() {
  int i = j, j;
  j = 42;
}

идентификатор j объявляется дважды как имя (и используется дважды).Декларативная область первого j включает весь пример.Потенциальная область действия первого j начинается сразу после этого j и продолжается до конца программы, но его (фактическая) область действия исключает текст между, и}.Декларативная область второго объявления j (j непосредственно перед точкой с запятой) включает весь текст между {и}, но его потенциальная область действия исключает объявление i.Область действия второго объявления j такая же, как и его потенциальная область.- конец примера]

Почему вы видите такие переменные результаты от IDEone, я не знаю.Он не предоставляет много ручек для выяснения того, что происходит. Wandbox является одной из нескольких альтернатив, которые предоставляют множество ручек и не демонстрируют такой же изменчивости для этого случая.

0 голосов
/ 16 октября 2018

Это UB, чтобы переопределить переменную в закрытой области видимости?

Нет, это не так.

Ошибка компилятора, которую вы видите, скорее всего, вызванатот факт, что внешний i объявлен, но не используется.

В противном случае ваш код просто в порядке.

Он отлично работает для меня на https://ideone.com/AwVJqZ, а также на моем рабочем столе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...