12
#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::或声明的情况下使用,但我不能使用orusing std::ispunct;来做到这一点。为什么会这样?std::coutstd::cin

4

3 回答 3

17

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

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

编辑:

至于为什么来自 C 的东西在全局命名空间中而不是在std命名空间中,我认为这与允许 C 代码通过 C++ 编译器进行最小更改进行编译有关,因为C++ 旨在与 C 兼容

根据评论,允许但不是ispunct必须位于全局命名空间中(但必须位于命名空间中),在. 但是,如果您改为包含,则需要位于全局命名空间中。std<cctype><ctype.h>ispunct

于 2013-08-04T20:03:49.690 回答
3

xxx.h除了名称空间之外,::std即使您包含标头的cxxx版本,也允许C 名称(从包含 C 标头中获得的名称)位于全局名称空间中。这样做是因为如果您提供 C++ 实现而不是 C 实现(因此实际的 C 标头来自您无法控制的编译器),那么在全局命名空间中没有这些可能会成为问题。

在您的情况下,ispunct来自 header ctype.h。当您包含cctype标头时,这又包含在全局命名空间ctype.h中声明符号的标头。ispunct

于 2013-08-04T20:07:26.033 回答
2

从 C 派生的 C++ 标头(例如<cctype>)需要将它们声明的事物的名称放在命名空间中std,并且允许它们也将它们放置在全局命名空间中。正式地,这在 C++11 之前是不允许的,但是不允许这些标头将名称放入全局命名空间的旧规则无法合理实现,并且通常被忽略。

于 2013-08-04T20:47:06.530 回答