我看到了这两个短语的用法:全局范围和全局命名空间。他们之间有什么区别?
答案 0 :(得分:80)
在C ++中,每个名称的范围都超出了它的范围。范围可以通过多种方式定义:它可以由 namespace , functions , classes 和 {}
因此,全局或其他命名空间定义范围。全局命名空间指的是使用::
,并且在此命名空间中定义的符号被称为具有全局范围。默认情况下,符号存在于全局命名空间中,除非它在块中定义,以关键字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's scope!
}
}
class A
{
int a; //its scope is the class itself.
//outside A, it doesn't exist.
};
另请注意, name 可以由命名空间,函数或类定义的内部作用域隐藏。因此,名称空间a
中的名称N
会在全局namspace中隐藏名称a
。同样,函数和类中的名称隐藏了全局命名空间中的名称。如果遇到这种情况,那么可以使用::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
}
}
答案 1 :(得分:4)
“范围”是比“命名空间”更通用的术语。每个命名空间,类和代码块都定义了一个范围,在该范围内可以使用在其中声明的名称;命名空间是在类和函数之外声明的名称的容器。
“全局范围”和“全局命名空间”可以或多或少地互换使用;命名空间中声明的名称范围涵盖整个命名空间。如果你特别指的是命名空间,请使用“namespace”;如果你指的是其中名称的可见性,请使用“scope”。
答案 2 :(得分:4)
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,因为我们已经要求全局命名空间::
。
命名空间语义大多是逻辑上的,它是一种将symblos彼此隔离的方式,希望避免名称冲突,它不会影响对象的生命周期。
另一方面,范围表示一个对象的生命周期,全局a
在本地a
之前存在,因为它比main执行得早得多。但是,范围也强制符号上的命名空间,但不像namespace
那样。有不同类型的范围,global
,class
,function
,block
,file
等......
令人困惑的部分是,范围有时会被重载以表示特定符号的可见性,这是从C借用的东西,其中命名空间的概念不存在,范围用于表示生命周期和可见性。但是在C ++中,规则有所改变,但术语 scope 仍以相同的方式使用,因为这两种语言共享大量概念。
答案 3 :(得分:3)
例如,当您声明全局变量int i
时,我们会说i is in the global namespace
和has the global namespace scope
。就是这样。
摘自C ++ 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).
答案 4 :(得分:2)
@Dmitriy Ryajov
这个话题有点旧,但我想就此提供帮助。我认为你不应该让事情变得比实际更复杂。标识符的Scope
是计算机程序的一部分,其中标识符(引用程序中某个实体的名称)可用于查找被引用的实体。因此术语范围仅适用于标识符,我们不应将其与对象的生命周期混合。它们有些联系,但不应混淆。对象的生命周期由我们为该对象分配内存的位置表示。因此,例如,如果在堆栈上分配了内存,则在函数完成后将立即释放内存。所以它取决于我们存储对象的位置,并且表示它的生命周期。范围只说:“这是一个对象的名称,我们可以在此之前使用此名称作为对象”。因此,正如我所说的,术语scope
仅用于对象的标识符,而生命周期是由我们存储对象的位置表示的其他内容。
此外,我想谈谈与此密切相关的linkage
。这有时也令人困惑。假设我们在translation unit
中有一些引用某些对象的标识符。 other
翻译单元中的相同标识符是否将引用相同的实体由链接表示。因此,例如,如果标识符具有外部链接,我们可以通过使用关键字extern
来声明该标识符引用的实体,但可以引用其他翻译单元。现在,假设我们不想在其他翻译单元中使用该实体。然后,实体将exist
直到程序结束,但是当我们不声明它时,我们将无法引用它。另请注意,现在我混合了术语链接和生命周期。但这是因为只有global
个实体具有外部链接。函数内的标识符不能从程序的其他部分引用。
结论:总是尽量保持简单。我很惊讶不同的人如何不同地谈论这些术语。单独编译的整个过程令人困惑,因为有多个术语具有几乎相同的含义,并且可能每个人都会陷入困境。