为什么在C ++中使用ispunct()时不需要std ::?

时间:2013-08-04 20:01:14

标签: c++ std

#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::coutstd::cin执行此操作。为什么会这样?

3 个答案:

答案 0 :(得分:17)

这意味着ispunct是全局命名空间的一部分,而不是std命名空间。这可能是因为ispunct是从C带来的函数之一(因此它在cctype中)。

另一方面,coutcinstd命名空间的一部分,而不是全局命名空间。

编辑:

至于为什么来自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才允许这样做,但是那些不允许将名称放入全局命名空间的旧规则无法合理地实现,并且通常被忽略。