Почему этот C ++ работает? (переменные с тем же именем) - PullRequest
5 голосов
/ 11 ноября 2010

Хорошо, я хочу знать, почему этот код работает, я только что понял, что у меня есть две переменные с одинаковым именем в одной и той же области видимости.

Я использую g ++ (gcc 4.4).

for(int k = 0 ; k < n ; k++)
    {
        while(true)
        {
            i = Tools::randomInt(0, n);
            bool exists = false;

            for(int k = 0 ; k < p_new_solution_size ; k++)
                if( i == p_new_solution[k] )
                {
                    exists = true;
                    break;
                }
            if(!exists)
                break;
        }

        p_new_solution[p_new_solution_size] = i;
        p_new_solution_size++;
    }

Ответы [ 5 ]

11 голосов
/ 11 ноября 2010

k во внутреннем контуре для теней петли (или скрывает) k во внешнем контуре для петли.

Вы можете объявить несколько переменных с одинаковыми именами в разных областях. Очень простым примером будет следующий:

int main()
{
    int a;       // 'a' refers to the int until it is shadowed or its block ends
    { 
        float a; // 'a' refers to the float until the end of this block
    }            // 'a' now refers to the int again
}
4 голосов
/ 11 ноября 2010

Хорошо, я хочу знать, почему этот код работает, я только что понял, что у меня есть две переменные с одинаковым именем в одной и той же области видимости.

Вы, кажется, смущены областями видимости. Они не "в одной и той же" области видимости ... цикл 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: если вы это делаете тогда вы можете иногда указывать его явно (если он ограничен пространствами имен и классами, но если он находится в теле функции, вам в конечном итоге потребуется изменить имя своей собственной переменной цикла (или создать ссылку или что-то на нее, прежде чем вводить одноименное имя) переменная)).

2 голосов
/ 11 ноября 2010

Из стандартных документов, Сек. 3.3.1

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

Это может показаться запутанным в вашем первом чтении, но это действительно отвечает на ваш вопрос.

Потенциальная область действия совпадает с областью действия объявления, если не происходит другое (внутреннее) объявление. Если это произошло, потенциальная область действия внешнего объявления - удалено и - всего лишь удержания внутреннего объявления.

Надежда ясна, и это помогает ..

1 голос
/ 11 ноября 2010

Поскольку вам разрешено иметь две переменные с одним и тем же именем в одной и той же области видимости, но не в пределах одного пространства объявлений.Компилятор берет наиболее локальную переменную с соответствующим именем, подобно тому, как вы можете «скрыть» глобальные переменные имени X с помощью переменной-члена с именем X. Однако вы должны получить предупреждение.

0 голосов
/ 11 ноября 2010

В C / C ++ область действия переменной ограничена фигурными скобками , поэтому следующий код действителен для компилятора:

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