名称空间具有未命名的名称空间,声明了相同的变量
namespaces having unnamed namespace with the same variable declared
我尝试了下面的虚拟代码来测试未命名的命名空间。
我有以下输出
ctor 1
ctor 0
3
5
我对这个有点困惑。
- 我期待编译器的错误,说它无法解决关于
a::m_a
的歧义。相反,它总是指向更少的嵌套。总是这样吗?c++遵循什么规则? - 似乎编译器按照顺序创建变量CMyObj写在文件上。总是这样吗?
- 是否有任何方法可以访问最嵌套的
m_a
变量源自main()
?
class CMyObj{
public:
CMyObj(int a){std::cout << "ctor " << a << std::endl; }
};
namespace a{
namespace{
int m_a=4;
int m_b=5;
CMyObj m_obj(1);
}
}
namespace a{
int m_a=3;
CMyObj m_obj(0);
}
int main(){
std::cout << a::m_a << std::endl; // which one?
std::cout << a::m_b << std::endl; // how this is possible?
return 0;
}
我没有c++ 03标准来检查那里的措辞,所以我将引用FDIS n3290。我认为这个问题的答案可以在3.4.3.2/2中的限定名称查找规则中找到:
对于命名空间X和名称m,命名空间限定的查找集S(X,m)定义如下:设S0(X,m)是X中所有m声明的集合和X的内联命名空间集合(7.3.1)。如果S0(X,m)不为空,则S(X,m)为S0(X,m);否则,S(X,m)是S(Ni,m)对于X及其内联命名空间集中使用指令指定的所有命名空间Ni的并集。
现在,请记住,未命名的命名空间是带有using指令的唯一命名空间。
首先看一下这个简化的代码(以及我的简化解释,您可以阅读§3.4.3.2了解详细信息):
namespace a
{
int x;
}
int main()
{
int i = a::x;
}
考虑当我们说a::x
时会发生什么。首先,编译器枚举a
中x
的所有声明。如果它找到一个明确的x
,它就成功完成。否则,它会递归地搜索using指令声明的名称空间。如果它从未找到结果,则程序是病态的。
namespace a
{
int x;
}
namespace b
{
using namespace a;
}
int main()
{
int i = b::x;
}
在这里,它没有在b
中找到x
,所以它搜索名称空间a
(因为using-directive)并找到它。现在应该可以理解为什么这不是二义性了:
namespace a
{
int x;
}
namespace b
{
using namespace a;
int x;
}
int main()
{
int i = b::x;
}
这里,它在b
中找到x
,而从不考虑a
。现在考虑一下,未命名的名称空间实际上只是一个具有唯一未知名称的名称空间:
namespace b
{
namespace
{
int x;
}
// this is what an unnamed namespace expands to (in exposition)
namespace __unique__ {}
using namespace __unique__;
namespace __unique__
{
int x;
}
int x;
}
int main()
{
int i = b::x;
}
和前面一样,在b
中找到x
而不考虑未命名的名称空间。你的代码是类似的
我应该花时间在规范中找到确切的定义,但是当您有一个匿名(未命名)名称空间时,编译器实际上会生成一个混乱的名称。当你写
a::m_b
在第二个std::cout
语句中,编译器会自动替换被修改过的名称,以便您可以访问它。引用Gene Bushuyev随后的回答:
现在,请记住,未命名的名称空间是唯一命名的名称空间
在名字冲突的情况下,编译器知道a::m_a
的意思,所以它使用它。它位于名称空间的顶层。我认为此时没有任何方法可以获得m_a的未命名命名空间副本。
这个页面很好地解释了名称空间。Winterdom: c++命名空间
没有歧义,因为namespace::<unnamed>::m_a
的作用域是外部命名空间(namespace::a
)。没有办法在main函数中访问namespace::<unnamed>::m_a
,这就是为什么没有歧义。尝试编译以下代码,您将得到错误:
namespace ns{
namespace {
int a = 2;
}
int a = 3;
int c = a;
}
位于同一翻译单元中的全局变量将按照声明的顺序初始化。在不同翻译单元中声明的全局变量的初始化顺序未定义
- 如果我们通过引用传递变量,则递归中使用的堆栈空间量是否为零?
- 在命名空间 c++ 中正确声明 extern 变量
- 在命名空间中声明变量,在 main 中定义它,使其对所有其他文件可见
- 在命名空间中定义变量
- 初始化命名空间中的变量是否类似于将它们初始化为类成员?
- 如何访问嵌套在命名命名空间中的未命名命名空间变量?
- 命名空间内C++变量声明
- C++从 std::async 函数读取命名空间中的全局变量标志
- 在Visual Studio中生成的匿名命名空间变量的损坏名称的数字部分是什么意思
- C++:.cpp中"Redeclare"外部命名空间变量
- 作用域中定义的变量与注入该作用域的命名空间变量
- Metal - 线程本地的命名空间变量?
- 在lambda中捕获名称空间变量
- C++VS2010链接器关于命名空间变量的错误
- 如果全局中存在相同的变量,如何访问匿名命名空间变量
- 内联命名空间变量有内部链接吗?如果没有,为什么下面的代码有效
- 静态成员变量和命名空间变量有什么区别?
- 命名空间变量的多重定义,C++编译
- 如何查找声明名称空间变量的文件
- 与命名空间变量进行比较