using 命名空间 std 的顺序;并包括?
我最近看到这段代码被用在一个 C++ 项目的源文件中:
using namespace std;
#include <iostream>
忽略所有关于 using namespace std
是否是一个好主意的问题,上面的代码是否合法?文件中这两行之前没有任何代码。
我本以为这不会编译,因为 namespace std
尚未在范围内声明,直到 #include
指令将其包含到文件中,但是使用该项目的构建系统,编译得很好。如果有人有规范相关部分的链接,我们将不胜感激。
I recently saw this code being used in a source file in a C++ project:
using namespace std;
#include <iostream>
Ignoring all issues of whether it's a good idea to have using namespace std
at all, is the above code even legal? There is no code in the file before these two lines.
I would have thought that this wouldn't compile, since namespace std
hasn't been declared in scope until the #include <iostream>
directive includes it into the file, but using the build system for the project this was compiling just fine. If someone has a link to a relevant part of the spec, that would be most appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
也许是一个有趣的数据点。 编译以下内容时
当我使用 g++ 4.5.2
,我得到:需要明确的是,这两行是我编译的整个源文件。
此时,
std
和no_such_namespace
都没有被定义为命名空间,但 g++ 仅抱怨第二个。在没有声明的情况下,我认为标识符std
没有什么特别之处。我认为@James Kanze 是对的,这是 g++ 中的一个错误。编辑:已经报道过。(5年前!)
更新:现在已经8年多了,还没有分配给任何人,更不用说修复了。 g++ 4.9.2 展示了这个问题。 clang++ 3.5 没有,但它会针对
std
发出警告,并针对no_such_namespace
发出致命错误:更新:截至 2021 年 9 月 24 日,错误报告仍处于开放状态该错误存在于 g++ 11.2.0 中。 2021 年 7 月 24 日发布的评论建议 g++ 应对此发出警告。
A perhaps interesting data point. When I compile the following:
with g++ 4.5.2, I get:
To be clear, those two lines are the entire source file I compiled.
Neither
std
norno_such_namespace
has been defined as a namespace at that point, but g++ complains only about the second. I don't think there's anything special about the identifierstd
in the absence of a declaration of it. I think @James Kanze is right that this is a bug in g++.EDIT: And it's been reported. (5 years ago!)
UPDATE: Now it's more than 8 years, and still hasn't been assigned to anyone, much less fixed. g++ 4.9.2 exhibits the problem. clang++ 3.5 doesn't, but it issues a warning for
std
and a fatal error forno_such_namespace
:UPDATE: As of 2021-09-24, the bug report is still open and the bug exists in g++ 11.2.0. A comment posted 2021-07-24 suggests that g++ should warn about this.
我不认为这是合法的,但标准并不是100%明确的。
基本上,名称查找(如第 3.4 节中定义)无法找到以前的名称
命名空间的声明,因为没有命名空间。一切
取决于:
是否是命名空间的声明。我没有看到任何文字
§7.3.4 说 using-directive 声明了指定的
命名空间。 G++ 允许您的代码,但恕我直言,这是一个错误。
I don't think it's legal, but the standard isn't 100% clear about it.
Basically, name lookup (as defined in §3.4) can't find a previous
declaration of the namespace, because there isn't one. Everything
hinges on whether:
is a declaration of the namespace or not. And I don't see any text in
§7.3.4 which says that a using-directive declares the nominated
namespace. G++ allows your code, but IMHO, this is a bug.
来自 SO/IEC 14882:2003
。因此,如果它碰巧起作用,那么它只是侥幸并且不可移植。
From SO/IEC 14882:2003
So if it happens to work, it's a fluke and not portable.
此代码是未定义的行为 [lib.using.headers]:
您引用
std
,然后包含一个声明它的标头。即使这仍然是未定义的行为:This code is undefined behavior [lib.using.headers]:
You reference
std
and then include a header that declares it. Even this is still undefined behavior:我认为标准(包括 C++0x)在这种情况下存在缺陷。
我们在第 3.3.6 节 (
[basic.scope.namespace]
) 中有:和
因此,
命名空间 std
是全局命名空间的成员,名称的范围从声明点开始。3.3.2 (
[basic.scope.pdecl]
) 告诉我们:并且所有例外都不适用于名称空间。
因此命名空间名称不能在其声明符之前使用,但命名空间名称不是声明符。哎呀。
I think there's a flaw in the standard (including C++0x) with respect to this case.
We have in section 3.3.6 (
[basic.scope.namespace]
):and
So
namespace std
is a member of the global namespace, and the scope of the name starts at the point of declaration.And 3.3.2 (
[basic.scope.pdecl]
) tells us:And none of the exceptions apply to namespaces.
So a namespace name cannot be used before its declarator, but a namespace name isn't a declarator. Oops.
最近,我遇到了同样的问题,我的技术主管建议我; using 命名空间不能保证方法的可见性,除非具有相关方法的命名空间包含在 using .h 文件中。
包括头文件解决了这个问题。
Recently i faced the same issue and been advised by my tech lead that; using namespace does not guarantee the visibility of the methods until the namespace with related methods are included in the file using .h file.
including the header file resolved the issue.