C++ 全局作用域与全局命名空间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10269012/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Global scope vs global namespace
提问by scdmb
I saw usages of these two phrases: global scope and global namespace. What is the difference between them?
我看到了这两个短语的用法:全局作用域和全局命名空间。它们之间有什么区别?
回答by Nawaz
In C++, every name has its scope outside which it doesn't exist. A scope can be defined by many ways : it can be defined by namespace, functions, classesand just { }.
在 C++ 中,每个名称都有其不存在的范围。作用域可以通过多种方式定义:它可以通过命名空间、函数、 类和仅{}来定义。
So a namespace, global or otherwise, defines a scope. The global namespace refers to using ::
, and the symbols defined in this namespace are said to have global scope. A symbol, by default, exists in a global namespace, unless it is defined inside a block starts with keyword namespace
, or it is a member of a class, or a local variable of a function:
因此,一个命名空间,无论是全局的还是其他的,都定义了一个范围。全局命名空间指的是 using ::
,在这个命名空间中定义的符号被称为具有全局作用域。默认情况下,符号存在于全局命名空间中,除非它定义在以关键字开头的块中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.
};
Also note that a namecan be hidden by inner scope defined by either namespace, function, or class. So the name a
inside namespace N
hides the name a
in the global namspace. In the same way, the name in the function and class hides the name in the global namespace. If you face such situation, then you can use ::a
to refer to the name defined in the global namespace:
另请注意,名称可以被命名空间、函数或类定义的内部作用域隐藏。所以a
命名空间内的名称N
隐藏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
}
}
回答by Eric Z
When you declare a global variable int i
for example, we say i is in the global namespace
and has the global namespace scope
. That's all.
int i
例如,当您声明一个全局变量时,我们说i is in the global namespace
和has the global namespace scope
。就这样。
Excerpt From C++03:
摘自 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).
回答by Mike Seymour
"Scope" is a more general term than "namespace". Every namespace, class and code block defines a scope in which names declared inside it can be used; a namespace is a container for names declared outside classes and functions.
“范围”是比“命名空间”更通用的术语。每个命名空间、类和代码块都定义了一个作用域,在该作用域中可以使用在其中声明的名称;命名空间是在类和函数之外声明的名称的容器。
"Global scope" and "global namespace" can be used more or less interchangeably; the scope of a name declared in a namespace covers the whole of that namespace. Use "namespace" if you're specifically referring to the namespace, and "scope" if you're referring to the visibility of names inside it.
“全局范围”和“全局命名空间”或多或少可以互换使用;在命名空间中声明的名称的范围涵盖了整个命名空间。如果您特指命名空间,请使用“命名空间”,如果您指的是其中名称的可见性,请使用“范围”。
回答by dryajov
Scope denotes the lifetime of an object, you can have a global variable that will exist as long as your program executes, or you can have a variable with a block scope that will exist as long as that block of code executes. Consider this example:
作用域表示对象的生命周期,您可以拥有一个只要程序执行就存在的全局变量,或者您可以拥有一个具有块作用域的变量,只要该代码块执行就一直存在。考虑这个例子:
#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;
}
When executed the statement will print local a is: 200
, that is expected obviously, because we're redefining a
in main
which leaves in the scope of it's enclosing block. We also print the global ::a
which again prints the expected value 100, because we have asked for the global namespace ::
.
当执行该语句将打印local a is: 200
,这显然是预期的,因为我们正在重新定义a
在main
其叶子在范围它的封闭块。我们还打印了 global ::a
,它再次打印了预期值 100,因为我们已经要求了 global namespace ::
。
A namespace semantics are mostly logical, it is a way of isolating symblos from one another, in the hope to avoid name clashes, it does not affect the lifespan of an object.
命名空间语义大多是合乎逻辑的,它是一种将符号相互隔离的方式,希望避免名称冲突,它不会影响对象的生命周期。
Scope on the other hand, denotes the lifespan of an object, the global a
sprung into existence before the local a
because it gets constructed much earlier than main gets executed. However, scope also forcesa namespace on the symbol, but not in the same way that a namespace
does. There are different kind of scopes, global
, class
, function
, block
, file
etc...
另一方面,作用域表示一个对象的生命周期,全局a
在局部之前突然出现,a
因为它比 main 被执行的时间早得多。然而,作用域也强制在符号上使用命名空间,但与 a 的namespace
方式不同。有不同种类的作用域,global
, class
, function
, block
,file
等等...
The confusing part is that scope is sometimes overloaded to denote the visibility of a particular symbol, which is something borrowed from C, where the notion of namespaces did not exist and scope was used to denote both, lifespan and visibility. In C++, however the rules changed a bit,but the term scopeis still used the same way because the two languages share a great deal of concepts.
令人困惑的部分是范围有时被重载以表示特定符号的可见性,这是从 C 借来的东西,其中名称空间的概念不存在并且范围被用来表示寿命和可见性。在 C++ 中,虽然规则发生了一些变化,但术语范围仍然以相同的方式使用,因为这两种语言共享大量概念。
回答by LearningMath
@Dmitriy Ryajov
@德米特里里亚约夫
The topic is a little bit old but I want to offer my help about this. I think that you should not make things more complicated than they really are. Scope
of an identifier is the part of a computer program where the identifier, a name that refers to some entity in the program, can be used to find the referred entity. So the term scope only applies to identifiers and we should not mix it with the lifetime of the object. They are somewhat connected but should not be mixed up. The lifetime of the object is denoted by where we allocate the memory for that object. So, for example, if a memory is allocated on the stack, it will be freed as soon as the function finishes. So it depends on where we store the object and that denotes its lifetime. The scope only says: "Here is a name for an object and we can use this name for the object till then and then". So, as I said, the term scope
is only for identifiers of the objects and the lifetime is something else wich is denoted by where we store the object.
这个话题有点老了,但我想就此提供帮助。我认为你不应该让事情变得比实际情况更复杂。Scope
标识符是计算机程序的一部分,其中标识符是指程序中某个实体的名称,可用于查找所引用的实体。因此,术语范围仅适用于标识符,我们不应将其与对象的生命周期混为一谈。它们有些关联,但不应混淆。对象的生命周期由我们为该对象分配内存的位置表示。因此,例如,如果在堆栈上分配了内存,则在函数完成后将立即释放它。所以这取决于我们存储对象的位置,这表示它的生命周期。作用域只说:“这是一个对象的名称,我们可以一直使用这个名称作为对象”。所以,正如我所说,这个词scope
仅用于对象的标识符,生命周期是其他东西,由我们存储对象的位置表示。
Additionally, I want to say something about linkage
which is closely related to this. This can be also sometimes confusing. Let's say we have some identifiers in the translation unit
that refer to some objects. Whether the same identifiers in other
translation unit will refer to the same entities is denoted by the linkage. So, for example, if an identifier has an external linkage, we can refer to the entity that this identifier refers to but from other translation unit by declaring it with keyword extern
. Now, let's say we don't want to use that entity in other translation units. Then, the entity will exist
till the program finishes but when we don't declare it, we won't be able to refer to it. Also note that now i mixed the terms linkage and lifetime. But this is because only global
entities have external linkage. An identifier inside a function can't be refered to from the other parts of the program.
另外,我想说一些linkage
与此密切相关的事情。这有时也会令人困惑。假设我们有一些标识符translation unit
指向一些对象。other
翻译单元中的相同标识符是否指代相同的实体由链接表示。因此,例如,如果一个标识符有一个外部链接,我们可以通过用关键字声明它来引用这个标识符所指但来自其他翻译单元的实体extern
。现在,假设我们不想在其他翻译单元中使用该实体。然后,实体会exist
一直到程序完成,但是当我们不声明它时,我们将无法引用它。另请注意,现在我混合了术语链接和生命周期。但这只是因为global
实体有外部联系。不能从程序的其他部分引用函数内的标识符。
Conclusion: Always try to keep things simple. I was surprised how different people talk about these terms differently. The whole process of separate compilation is confusing, because there are multiple terms which have almost the same meaning and probably everyone will get stuck at this point.
结论:总是尽量保持简单。我很惊讶不同的人如何以不同的方式谈论这些术语。单独编译的整个过程很混乱,因为有多个术语几乎具有相同的含义,可能每个人都会在这一点上卡住。