Глобальная область и глобальное пространство имен

Я видел использование этих двух фраз: глобальная область действия и глобальное пространство имен. В чем разница между ними?

Ответ 1

В С++ каждое имя имеет свою область, вне которой она не существует. Область может быть определена многими способами: она может быть определена пространством имен, функциями, классами и просто {}.

Таким образом, пространство имен, глобальное или иное, определяет область. Глобальное пространство имен относится к использованию ::, а символы, определенные в этом пространстве имен, имеют глобальную область видимости. Символ по умолчанию существует в глобальном пространстве имен, если только он не определен внутри блока, начинается с ключевого слова namespace, или он является членом класса или локальной переменной функции:

int a; //this a is defined in global namespace
       //which means, its scope is global. It exists everywhere.

namespace N
{
     int a;  //it is defined in a non-global namespace called `N`
             //outside N it doesn't exist.
}
void f()
{
   int a;  //its scope is the function itself.
           //outside the function, a doesn't exist.
   {
        int a; //the curly braces defines this a scope!
   }
}
class A
{
   int a;  //its scope is the class itself.
           //outside A, it doesn't exist.
};

Также обратите внимание, что имя может быть скрыто внутренней областью, определенной либо пространством имен, либо функцией, либо классом. Таким образом, имя a внутри пространства имен N скрывает имя a в глобальном namspace. Точно так же имя в функции и классе скрывает имя в глобальном пространстве имен. Если вы столкнулись с такой ситуацией, вы можете использовать ::a для обозначения имени, определенного в глобальном пространстве имен:

int a = 10;

namespace N
{
    int a = 100;

    void f()
    {
         int a = 1000;
         std::cout << a << std::endl;      //prints 1000
         std::cout << N::a << std::endl;   //prints 100 
         std::cout << ::a << std::endl;    //prints 10
    }
}

Ответ 2

"Сфера" - это более общий термин, чем "пространство имен". Каждое пространство имен, класс и блок кода определяет область, в которой могут использоваться имена, объявленные внутри нее; пространство имен - это контейнер для имен, объявленных вне классов и функций.

"Глобальная область видимости" и "глобальное пространство имен" могут использоваться более или менее взаимозаменяемо; область имени, объявленного в пространстве имен, охватывает все пространство имен. Используйте "пространство имен", если вы специально ссылаетесь на пространство имен и "область", если вы имеете в виду видимость имен внутри него.

Ответ 3

Scope обозначает время жизни объекта, вы можете иметь глобальную переменную, которая будет существовать до тех пор, пока выполняется ваша программа, или вы можете иметь переменную с областью блока, которая будет существовать до тех пор, пока выполняется этот блок кода. Рассмотрим этот пример:

#include <iostream>

int a = 100;

main () {
    int a = 200;

    std::cout << "local a is: " << a << std::endl;
    std::cout << "global a is: " << ::a << std::endl;

    return 0;
}

При выполнении инструкции будет напечатан local a is: 200, что ожидается, очевидно, потому что мы переопределяем a в main, который выходит в область действия этого блока. Мы также печатаем глобальный ::a, который снова выводит ожидаемое значение 100, потому что мы попросили глобальное пространство имен ::.

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

С другой стороны, область действия означает продолжительность жизни объекта, глобальная a возникла до локального a, потому что она создается намного раньше, чем выполняется main. Однако область видимости также создает пространство имен в символе, но не так, как это делает namespace. Существуют различные типы областей, global, class, function, block, file и т.д.

Запутанная часть состоит в том, что область иногда перегружается, чтобы обозначать видимость конкретного символа, который является чем-то заимствованным из C, где понятие пространств имен не существует, а область используется для обозначения как продолжительности жизни, так и видимости. В С++, однако, правила немного изменились, но термин scope по-прежнему используется одинаково, потому что два языка разделяют множество концепций.

Ответ 4

Когда вы объявляете глобальную переменную int i, например, говорим i is in the global namespace и has the global namespace scope. Это все.

Выдержка из С++ 03:

3.3.5 Namespace scope   

    The outermost declarative region of a translation unit is also a namespace, called
  the global namespace. A name declared in the global namespace has global namespace
  scope (also called global scope).

Ответ 5

@Dmitriy Ryajov

Тема немного старая, но я хочу предложить свою помощь об этом. Я думаю, что вы не должны усложнять ситуацию, чем они есть на самом деле. Scope идентификатора является частью компьютерной программы, где идентификатор, имя, которое относится к какой-либо сущности в программе, может использоваться для поиска упомянутого объекта. Таким образом, термин scope применим только к идентификаторам, и мы не должны смешивать его со временем жизни объекта. Они несколько связаны, но их не следует смешивать. Время жизни объекта обозначается тем, где мы выделяем память для этого объекта. Так, например, если память выделена в стеке, она будет освобождена, как только функция завершится. Таким образом, это зависит от того, где мы храним объект, а это означает его время жизни. Область действия только говорит: "Вот имя для объекта, и мы можем использовать это имя для объекта до тех пор, а затем". Итак, как я уже сказал, термин Scope предназначен только для идентификаторов объектов, а время жизни - это нечто другое, которое обозначается тем, где мы храним объект.

Кроме того, я хочу сказать что-то о linkage, которое тесно связано с этим. Иногда это может сбивать с толку. Скажем, у нас есть некоторые идентификаторы в translation unit, которые относятся к некоторым объектам. Будут ли обозначены те же идентификаторы в блоке перевода other для одних и тех же объектов. Так, например, если идентификатор имеет внешнюю связь, мы можем обратиться к сущности, к которой относится этот идентификатор, но от другой единицы перевода, объявив ее ключевым словом extern. Теперь предположим, что мы не хотим использовать эту сущность в других единицах перевода. Затем объект будет exist, пока программа не завершится, но когда мы ее не объявим, мы не сможем ссылаться на нее. Также обратите внимание, что теперь я смешал термины linkage и lifetime. Но это потому, что только объекты global имеют внешнюю связь. Идентификатор внутри функции нельзя ссылаться на другие части программы.

Вывод: всегда старайтесь держать вещи простыми. Я был удивлен, как разные люди говорят об этих терминах по-разному. Весь процесс отдельной компиляции сбивает с толку, потому что есть несколько терминов, которые имеют почти одинаковый смысл и, вероятно, все застрянут на этом этапе.