C++ 为什么可以';在未命名的命名空间中声明变量后,我是否在全局范围内定义变量?
据我理解:C++ 为什么可以';在未命名的命名空间中声明变量后,我是否在全局范围内定义变量?,c++,linkage,C++,Linkage,据我理解: 未命名命名空间中声明的名称是 使用extern说明符,变量不会自动定义(默认初始化) 我希望下面声明一个变量,然后定义同一个变量: // Declare ::<unnamed>::my_obj with internal linkage and add my_obj to the // enclosing namespace scope (the global namespace scope). namespace { extern int my_obj; } //
- 未命名命名空间中声明的名称是
- 使用
说明符,变量不会自动定义(默认初始化)extern
// Declare ::<unnamed>::my_obj with internal linkage and add my_obj to the
// enclosing namespace scope (the global namespace scope).
namespace { extern int my_obj; }
// Expected: Define the variable declared above.
// Actual: Declare and define a new object, ::my_obj.
int my_obj(42);
//声明:::具有内部链接的my_obj,并将my_obj添加到
//封闭命名空间范围(全局命名空间范围)。
命名空间{extern int my_obj;}
//预期:定义上面声明的变量。
//实际:声明并定义一个新对象::my_obj。
int my_obj(42);
相反,它声明了两个不同的对象,并警告我未使用的extern int my_obj
为什么第二个
my_obj
不定义第一个my_obj
?它不在范围内吗?未命名的命名空间不是全局命名空间。它是一个特定的名称空间,仅在它出现的翻译单元中可见
更详细地描述了这一点
如果您试图在同一翻译单元中使用在未命名命名空间中定义的符号,请使用它!在范围之内。您不需要一个extern
来自:
使用extern存储类说明符声明的变量是对在程序的任何源文件的外部级别上定义的具有相同名称的变量的引用。内部外部声明用于使外部级别变量定义在块中可见除非在外部级别声明,否则使用extern关键字声明的变量仅在声明该变量的块中可见。由于对象是在命名空间中声明的,因此必须在同一命名空间中定义该对象(或者更确切地说,如果一个名称在一个名称空间中用作声明,而在该名称空间之外用作定义,则它引用两个不同的实体)- 在未命名命名空间中声明的名称将添加到封闭的 命名空间范围 -并不意味着你认为它能做什么 C++11标准规定,未命名的命名空间定义的行为就像它被以下内容替换一样: (对于格式稍作解释;初始“inline”是可选的,当它出现在未命名的命名空间定义中时出现) 那么,您是否希望:
namespace a_name {
extern int a;
}
using namespace a_name;
int a = 4;
…第一次提到a
(在名称空间内)将声明变量,第二次定义它?(如果你愿意,至少这是一致的。但是如果你不愿意,你需要认识到标准明确规定你应该从未命名的名称空间获得相同的行为)
我不相信有任何机制可以在一个名称空间中声明一个成员,并在另一个名称空间中为同一成员提供定义,即使该成员在第二个名称空间中可见
针对以下评论:
extern
导致声明不是一个定义。我已经删除了声明extern
没有效果,这主要是指链接;extern
没有在未命名的命名空间中授予名称外部链接是正确的,因为C++11(包括修订版)。虽然在C++03中,它可能在技术上授予了外部链接,但这只是作为声明/定义的一个属性;符号在翻译单元外仍然不可见,对链接器也没有特殊的可见性。C++03中未命名名称空间的成员上的extern
的意义显然是显而易见的n表示该成员作为常量表达式的可用性,如果它是常量
限定指针const
。它确实无法使用GCC编译,但它使用Clang和英特尔编译器Icc成功编译。对于三种编译器中的任何一种,内联命名空间中声明的符号都是链接级别的本地符号(例如,可以使用objdump
看到)-链接器级别的符号可见性与产生的错误之间没有因果关系。C++11明确声明(3.5),大意是
外部
-合格符号应具有内部链接,如果
驻留在未命名的命名空间中(特别是:具有
上面没有给出内部链接的命名空间范围与封闭命名空间具有相同的链接(如果它是-变量的名称;或…)。此外,const
-具有内部链接的声明变量应该可以在需要常量表达式的上下文中使用。通过阅读该标准,可以确定GCC编译器在这种情况下的行为不正确namespace A
{
void foo();
}
using namespace A;
void foo() // <- Defines `::foo`, not `A::foo`
{
}
// `A::foo` remains undefined
名称空间A
{
void foo();
}
使用名称空间A;
void foo()//未命名命名空间中声明的“第一个引号”名称添加到全局命名空间范围的位置(
namespace A
{
void foo();
}
using namespace A;
void foo() // <- Defines `::foo`, not `A::foo`
{
}
// `A::foo` remains undefined