#include <iostream>
#include <string>
#include <cctype>
using std::string;
using std::cin;
using std::cout; using std::endl;
int main()
{
string s("Hello World!!!");
decltype(s.size()) punct_cnt = 0;
for (auto c : s)
if (ispunct(c))
++punct_cnt;
cout << punct_cnt
<< " punctuation characters in " << s << endl;
}
似乎我可以在没有ispunct()
的情况下使用std::
或声明using std::ispunct;
,但我无法使用std::cout
或std::cin
执行此操作。为什么会这样?
答案 0 :(得分:17)
这意味着ispunct
是全局命名空间的一部分,而不是std
命名空间。这可能是因为ispunct
是从C带来的函数之一(因此它在cctype
中)。
另一方面,cout
和cin
是std
命名空间的一部分,而不是全局命名空间。
至于为什么来自C的东西都在全局命名空间而不是std
命名空间中,我认为它与C ++编译器允许C代码编译有关自C++ aims to be compatible with C以来发生了变化。
根据评论,ispunct
允许,但不是必需,位于全局命名空间中(但必需 > {在std
命名空间中,位于<cctype>
。但是,如果您添加了<ctype.h>
,则ispunct
必需将位于全局命名空间中。
答案 1 :(得分:3)
除了xxx.h
命名空间之外,即使您包含::std
,C名称(从C中包含cxxx
标题的名称)也可以位于全局名称空间中标题的版本。这样做是因为如果您提供C ++实现而不是C实现(因此实际的C头来自您不能控制的编译器),那么在全局命名空间中不存在这些问题可能是一个问题。
在您的情况下,ispunct
来自标题ctype.h
。当您包含cctype
标头时,这又包含ctype.h
标头,该标头在全局命名空间中声明符号ispunct
。
答案 2 :(得分:2)
从C派生的C ++标题(例如<cctype>
)需要将他们在名称空间std
中声明的内容的名称放在允许的中它们在全局命名空间中。形式上,直到C ++ 11才允许这样做,但是那些不允许将名称放入全局命名空间的旧规则无法合理地实现,并且通常被忽略。