5

C++ 编程语言:特别版在第 431 页上声明...

For every header < X.h > defining part of the C standard library in the global namespace and also in namespace std, there is a header < cX > defining the same names in the std namespace only.

但是,当我在 <cX> 样式中使用 C 标头时,我不需要限定名称空间。例如...

#include <cmath>
void f() {
  double var = sqrt( 17 );
}

这会编译得很好。即使书中说使用 < cX > 标头仅在 std 命名空间中定义名称,您也可以在不限定命名空间的情况下使用这些名称。我在这里想念什么?

PS 使用 GNU.GCC 编译器

4

5 回答 5

9

MSVC 团队成员 Stephan T. Lavavej 在他的一篇博客文章 ( http://blogs.msdn.com/vcblog/存档/2008/08/28/the-mallocator.aspx#8904359):

> 还有, <cstddef>, <cstdlib>, and std::size_tetc 应该被使用!

我以前对此非常小心。C++98 有一个壮丽的梦想,其中<cfoo> 将声明命名空间 std 中的所有内容,然后使用 using 声明将所有内容<foo.h>包含<cfoo>并拖动到全局命名空间中。(这是 D.5 [depr.c.headers]。)

许多实现者都忽略了这一点(其中一些实现者对 C 标准库头文件几乎没有控制权)。因此,C++0x 已被更改以匹配现实。从 N2723 工作文件http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf开始,现在<cfoo>保证声明命名空间 std 中的所有内容,并且可能会或可能不会声明事物在全局命名空间内。<foo.h>恰恰相反:它保证在全局命名空间中声明所有内容,并且可能会或可能不会在命名空间 std 中声明事物。

实际上,在 C++0x中,<cfoo>无论如何,include 并不能防止在全局命名空间中声明所有内容。这就是为什么我不再打扰<cfoo>.

这是图书馆第 456 期,http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456

(C++0x 仍然弃用<foo.h>C 标准库中的头文件,这很有趣。)

我与 Lavavej 100% 同意,但<cfoo>即使在我第一次开始使用 C++ 时,我也从未尝试过非常小心地使用样式标头——标准 C 的标头太根深蒂固了——而且使用它们从来没有任何现实世界的问题(显然,使用<cfoo>样式标题从来没有任何现实世界的好处)。

于 2010-01-22T16:28:16.290 回答
6

C 库的规则与命名空间的 C++ 库不同

gcc 将Gcc 文档中的标准解释为

该标准规定,如果包含 C 样式的标头(在这种情况下为 <math.h>),则这些符号将在全局命名空间中可用,并且可能在命名空间 std:: 中可用(但这不再是硬性要求。)另一方面,包括 C++ 样式的标头 (<cmath>) 保证实体将在命名空间 std 中找到,也可能在全局命名空间中找到。

在 C0X++ 规范草案中,它在第 17.6.2.3 节标题中说

未指定这些名称是否首先在全局命名空间范围内声明,然后通过显式使用声明注入命名空间 std

于 2010-01-22T16:03:25.763 回答
4

如果不两次实现 C 库,就很难解决这个问题。请参阅DR 456,它基本上建议放弃该问题。

于 2010-01-22T16:03:24.850 回答
1

当它违反标准时,你为什么说“这会编译得很好”?谁允许您在不限定名称空间的情况下使用这些名称?您是否在特定实现上对此进行了测试并发现它有效?

我强烈建议不要使用某些特定的非标准功能,因为它恰好适用于您选择的编译器。这样的事情很容易破坏,也许是同一编译器的更高版本。

于 2010-01-22T15:54:02.213 回答
0

您可能缺少使用符合标准的编译器(或者您使用的编译器被配置为与预标准代码兼容)。

于 2010-01-22T15:52:33.630 回答