В чем разница между написанием ":: namespace :: identifier" и "namespace :: identifier"? - PullRequest
4 голосов
/ 27 ноября 2011

Я видел оба подхода в коде.Не могли бы вы объяснить, в чем разница между ними?Поскольку я думаю, что это связано с тем, как C ++ выполняет поиск в пространстве имен, не могли бы вы предоставить некоторую информацию об этом или, возможно, ссылку на хороший документ?Спасибо.

Ответы [ 2 ]

12 голосов
/ 27 ноября 2011

Пример:

#include <cstdio>

namespace x {
    const int i = 1;
}

namespace y {
    namespace x {
        const int i = 2;
    }

    void func()
    {
        std::printf("x::i = %d\n", x::i);
        std::printf("::x::i = %d\n", ::x::i);
    }
}

int main()
{
    y::func();
    return 0;
}

Выход:

x::i = 2
::x::i = 1

Пояснение:

  • Когда вы ссылаетесь на такой идентификатор, как x::i, используемое определение является «самым близким» x::i. Внутри ::y::func определение ::y::x::i ближе, чем определение ::x::i. В отличие от этого, такой функции ::y::std::printf нет, поэтому вместо нее используется ::std::printf.

  • Когда вы ссылаетесь на идентификатор, такой как ::x::i, возможной двусмысленности нет: он ищет пространство имен верхнего уровня с именем x, а затем находит внутри i.

Таким образом, использование :: в начале позволяет вам записать полное имя чего-то глобального. Это также позволяет различать локальные и глобальные переменные.

Пример 2:

#include <cstdio>
const int x = 5;
int main()
{
    const int x = 7;
    std::printf("x = %d\n", x);
    std::printf("::x = %d\n", ::x);
    return 0;
}

Выход:

x = 7
::x = 5
5 голосов
/ 27 ноября 2011

Это не имеет значения, по крайней мере, большую часть времени.

В формате ::identifier1::identifier2 предшествующее двоеточие говорит, что нужно искать глобальную область для identifier1, а затем искать identifier2 в этой области.

В формате identifier1::identifier2 вместо этого мы рассмотрим текущую область действия для identifier1. Если мы не найдем его, то будет произведен поиск родительской области и так далее, пока мы его не найдем. Затем мы ищем identifier2 в той области, которую только что нашли.

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

...