LINUX.ORG.RU

Вопрос по переопределению auto переменной

 


0

4

Наткнулся вот:

#include <vector>
#include <iostream>

int main(int argc, char** argv)
{
   std::vector<int> mVector;
   for (int i = 0; i < 10; ++i) {
      mVector.emplace_back(i);
   }

   for (auto&& intValue : mVector) {
      std::cout << "i = " << intValue << std::endl;
      int anotherValue = intValue + 10;
      if (anotherValue > 10) {
         int intValue = anotherValue;
         std::cout << "another int = " << intValue << std::endl;
      }
   }
   return 0;
}

Собираю как g++ -Wall autoname.cpp -o autoname и ничего, молчок.

Причём если убрать if, то получаю ожидаемое

autoname.cpp: In function ‘int main(int, char**)’:
autoname.cpp:14:11: error: redeclaration of ‘int intValue’
       int intValue = anotherValue;
           ^~~~~~~~
autoname.cpp:11:16: note: ‘int& intValue’ previously declared here
    for (auto&& intValue : mVector) {
                ^~~~~~~~

% g++ --version
g++ (Ubuntu 6.2.0-3ubuntu11~14.04) 6.2.0 20160901

Я что-то упустил или это таки косяк gcc?

★★★★★

В чём косяк то? Всё верно.

У переменных область видимости - блок.

Объявление имени в блоке может скрыть объявление этого имени в охватывающем блоке или глобальное имя.

То есть имя может быть замещено внутри блока и будет ссылаться там на другую сущность.

После выхода из блока имя восстанавливает свой прежний смысл.

fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

Объявление имени в блоке может скрыть объявление этого имени в охватывающем блоке или глобальное имя.

И компилер меня об этом всегда предупреждал, только не в этом случае. Если я поменяю

int intValue = anotherValue;
на
int anotherValue = intValue;
то получу ожидаемое:
autoname.cpp: In function ‘int main(int, char**)’:
autoname.cpp:15:14: warning: unused variable ‘anotherValue’ [-Wunused-variable]
          int anotherValue = intValue;

UVV ★★★★★
() автор топика
Ответ на: комментарий от UVV

Тут вообще другой ворнинг.

про неиспользуемую переменную

Если изменить

std::cout << «another int = » << intValue << std::endl;

на

std::cout << «another int = » << anotherValue << std::endl;

То он тоже пропадёт.

fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

Тут вообще другой ворнинг.
То он тоже пропадёт.

Точно, не заметил...

UVV ★★★★★
() автор топика
Ответ на: комментарий от fsb4000

Нашёл, походу надо включить -Wshadow, чтобы получить его. Мне всегда раньше казалось, что оно входит в -Wall

UVV ★★★★★
() автор топика
Ответ на: комментарий от UVV

Посмотреть какие флаги ворнингов включены при -Wall -Wextra можно следующей командой:

g++ -Q -Wall -Wextra --help=warning > warn.txt

fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

Кажется Visual studio 2015 кидает warning при сокрытии имён, но компилирует и работает тоже всё нормально.

ЕМНИП, VS как раз нихера не кидает, и даже жрет конструкции типа

int a = 1;
if (whatever) {
    int a = 1 + a;
    // ...
}

Stil ★★★★★
()
Ответ на: комментарий от Stil

ЕМНИП, VS как раз нихера не кидает, и даже жрет конструкции типа

Аналогично GCC у VS есть опции, выставь достаточно уровень предупреждений - и будут тебе сообщения.

anonymous
()

google://c++ variable shadowing

Kuzy ★★★
()
Ответ на: комментарий от Stil

Специально проверил код автора на VS 2015.

Выдало 3 ворнинга при уровне W4

(файл и номер строки) warning C4456: declaration of 'intValue' hides previous local declaration

(файл и номер строки) warning C4100: 'argv': unreferenced formal parameter

(файл и номер строки) warning C4100: 'argc': unreferenced formal parameter

fsb4000 ★★★★★
()

Хоспаде, когда ж ты уже начнешь читать и думать...

anonymous
()

Я что-то упустил или это таки косяк gcc?

Внутри одного скоупа вы пытаетесь объявить переменную дважды.
В случае if вы открываете новый скоуп и новая переменная объявляется уже в нем, затеняя переменную с таким же именем вне скоупа.
С таким же успехом можно было убрать if (anotherValue > 10), но оставить скоуп ({}).

andreyu ★★★★★
()

Я что-то упустил или это таки косяк gcc?

Ты что-то упустил.

В первом случае ты объявил две переменные с одиним именем в двух разных областях видимости. Всё ОК, компилятору насрать, сколько у тебя одноимённых переменных в разных областях видимости.

Во втором случае ты объявил две переменные с одним именем в одной области видимости. Компилятор тебе об этом и рассказал.

alexku
()
Ответ на: комментарий от jcd

- во-первых, хуже не будет и auto&& пофигу, что там (насколько я понял)
- во-вторых, в реальном коде оно не для int-вектора

UVV ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.