C++11在某些时候会包含<cstdlib>,而C++03则不会?

8
看看这个小程序。
#include <iostream>

int main(){

  int var = atoi("-99");      //convert string to int
  var = abs(var);             //takes absolute value
  std::cout << var+1 <<'\n';  //outputs 100

  return EXIT_SUCCESS;
}

编译将会生成以下错误信息:
$ g++ -o main main.cpp
main.cpp: In function ‘int main()’:
main.cpp:5:13: error: ‘atoi’ was not declared in this scope
main.cpp:6:16: error: ‘abs’ was not declared in this scope
main.cpp:9:10: error: ‘EXIT_SUCCESS’ was not declared in this scope

可以理解。所有这些都存在于“cstdlib”头文件中,我忘了包含它。
然而,编译时需要使用:
$ g++ -std=c++0x -o main main.cpp 

没有问题。


查看"cstdlib"头文件的源代码,我发现在底部有以下代码:

#ifdef __GXX_EXPERIMENTAL_CXX0X__
#  if defined(_GLIBCXX_INCLUDE_AS_TR1)
#    error C++0x header cannot be included from TR1 header
#  endif
#  if defined(_GLIBCXX_INCLUDE_AS_CXX0X)
#    include <tr1_impl/cstdlib>
#  else
#    define _GLIBCXX_INCLUDE_AS_CXX0X
#    define _GLIBCXX_BEGIN_NAMESPACE_TR1
#    define _GLIBCXX_END_NAMESPACE_TR1
#    define _GLIBCXX_TR1
#    include <tr1_impl/cstdlib>
#    undef _GLIBCXX_TR1
#    undef _GLIBCXX_END_NAMESPACE_TR1
#    undef _GLIBCXX_BEGIN_NAMESPACE_TR1
#    undef _GLIBCXX_INCLUDE_AS_CXX0X
#  endif
#endif

我不确定这是否相关..完整的头文件代码在这里

我的最终问题是,新标准是否保证当您包含iostream时,将在全局命名空间中引入所有的cstdlib?

我找不到任何关于此事的文档。对我来说似乎是这样,你觉得呢?

gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

3
顺便提一下,这个标题非常误导人。C++11 C++。它不是一个新的独立语言。 - R. Martinho Fernandes
1个回答

16
我的最终问题是,新标准是否保证在包含iostream时会将整个cstdlib引入全局命名空间?
并不是。如果需要其功能,您应该自己#include它。如果通过“免费”获取它,这表明您的头文件需要它,但这样您就依赖于C++库的实现细节。
顺便说一下,#include 不能保证将C函数带入全局命名空间(尽管在C ++实现中通常会这样做);它保证将它们放在namespace std中:
除18到30条和附录D中所述外,每个头文件cname的内容应与相应的头文件name.h的内容相同,如同通过包含指定的C标准库(1.2)或C Unicode TR适当版本中的那样。然而,在C++标准库中,声明(除了在C中定义为宏的名称之外)位于命名空间作用域(3.3.6)中的命名空间std中。这些名称的声明是否首先在全局命名空间作用域内进行,并通过显式using-declarations (7.3.3) 注入到命名空间std中是未指定的。(标准,第17.6.1.2节)

1
@Xploit:不用在意我之前的评论。<cstdlib>确实将atoi放置在命名空间std中;如果你的编译器也将其放置在全局命名空间中,那么这就是一个平台特定的扩展。 - Fred Foo
@larsmars 这不是一个功能,而是一个错误。这是全局命名空间的意外污染 - 这是库编写者难以避免的问题。gcc在逐步清除这些污染方面做得很好。顺便说一句,这是导致软件包在新版本的gcc下出现编译错误的主要原因之一,而在此之前它们可以正常编译。 - Gunther Piez
1
@larsmans 这不是一个错误,因为新的C++标准允许这种行为。<cfoo>版本的C头文件将所有内容放在std::中,并且也可能将它们放在全局命名空间中。<foo.h>头文件将所有内容放在全局命名空间中,并且也可能将它们放在std::命名空间中。抱歉,目前找不到链接。 - Sjoerd
2
发现链接!请查看此答案的评论https://dev59.com/xG445IYBdhLWcg3wBVvz#5079548 和官方条目456http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456 - Sjoerd
1
@Sjoerd:我再次检查了标准文本,似乎确实允许这样做。不过,OP 不应该依赖于 <cstdlib> 中声明的 ::atoi - Fred Foo
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接