C++ 为什么在C+;中使用ispunct()时不需要std::呢+;? #包括 #包括 #包括 使用std::string; 使用std::cin; 使用std::cout;使用std::endl; int main() { 字符串s(“你好,世界!!!”; decltype(s.size())punct_cnt=0; 用于(自动c:s) 如果(ispunt(c)) ++点状; cout

C++ 为什么在C+;中使用ispunct()时不需要std::呢+;? #包括 #包括 #包括 使用std::string; 使用std::cin; 使用std::cout;使用std::endl; int main() { 字符串s(“你好,世界!!!”; decltype(s.size())punct_cnt=0; 用于(自动c:s) 如果(ispunt(c)) ++点状; cout,c++,std,C++,Std,这意味着ispunct是全局名称空间的一部分,而不是std名称空间。这可能是因为ispunct是从C引入的函数之一(因此它在cctype中) 另一方面,cout和cin是std命名空间的一部分,而不是全局命名空间 编辑: P>关于为什么C中的事物位于全局命名空间中,而不是在 STD< /Calp>命名空间中,我相信这与允许C代码由最小的变化编译成C++代码有关,因为 根据注释,ispunt允许但不要求在全局命名空间中(但要求在std命名空间中),在中。但是,如果您包含,则ispunt必须位于全

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

另一方面,
cout
cin
std
命名空间的一部分,而不是全局命名空间

编辑: <> P>关于为什么C中的事物位于全局命名空间中,而不是在 STD< /Calp>命名空间中,我相信这与允许C代码由最小的变化编译成C++代码有关,因为

根据注释,
ispunt
允许但不要求在全局命名空间中(但要求
std
命名空间中),在
中。但是,如果您包含
,则
ispunt
必须位于全局命名空间中。

C名称(从C中包含
xxx.h
标题获得的名称)允许在全局命名空间中添加除<代码>::STD< /Cord>命名空间,即使您包括了“代码”> CXXX < /Cord>版本的头。这已经完成了,因为如果提供C++实现,而不是C实现,则不能在全局命名空间中拥有这些名称。(因此,实际的C头来自您不控制的编译器)


在您的例子中,
ispunct
来自头
ctype.h
。当您包括
cctype
头时,这又包括
ctype.h
头,它在全局命名空间中声明符号
ispunct

C++头来自C(例如
)需要将声明的内容的名称放入命名空间
std
,并且允许也将其放入全局命名空间。从形式上讲,直到C++11才允许这样做,但不允许这些头将名称放入全局命名空间的旧规则无法合理地实现通常会被忽略。

所有C都被放在全局命名空间中,因此C代码将按原样编译。@jalf:为了帮助代码读者更容易理解它。@Mehrdad我不明白,它复制了什么?它非常精确地表示值的类型应该与字符串的size函数的返回v所使用的类型相同值。它实际上并不等同于
size\u t
,而是等同于
std::string::size\u type
(通常,但不保证是相同的类型)这是一种非常规的表达方式,但我看不到不必要的重复。@jalf:std::string::size\u type不是
size\u t
,这是100%非法的,因为
std::basic\u string::size\u type
被定义为
std::allocator\u traits::size\u type
,而定义为
std::allocator::allocator\u type
r::size\u type定义为
size\u t
@jalf:关于复制,我是说这种编码惯例(即使用
decltype
而不是
auto
或实际类型)通常会导致代码重复,所以最好不要养成使用它的习惯,除非确实有必要。你说他们“被允许”位于全局命名空间中。这是否意味着给定的代码示例可能无法在另一个编译器中编译?或者如果您
#include
,则
ispunt
实际上保证位于全局命名空间中?它们实际上保证位于全局命名空间中。§N3337(C++11)第17.6.1.2.4节:每个标题<代码> *c*Nords/Code >与相应的标题<代码>名称> .<代码>一样,如C标准库或C++ Unicode TR中所规定的,如包含的内容。在名称空间标准的名称空间范围内。未指定这些名称是否首先在全局名称空间范围内声明,然后通过显式使用声明注入名称空间标准”(emph.mine)@peppe:谢谢。我正在搜索有关它的信息,但找不到。我一直认为它是可选的,因为最初的
cxxx
头被禁止在全局范围内包含名称;这是因为有困难而修改的。我本以为实现以前的rULE不会被认为不符合规范(但是,也许修订版在C++98发布之前就已经存在了,或者没有编译器真正实现了规范)“我会解决这个问题的。”佩普:我现在已经回到了我原来的版本,因为Pete Becker的回答和他对我的评论的回答。@佩普-第二条规则构建规则是“继续阅读”。下面引用的一句话是:“在C++标准库中,声明。(在C中定义为宏的名称除外)在命名空间std的命名空间范围(3.3.6)内。"从来没有任何意图要求
c*
头也将名称放入全局名称空间。事实上,最初的要求正好相反:它们不能将名称放入全局名称空间。这对于某些供应商来说基本上是不可实现的,因此规则被削弱以允许它。因此,我在更改之前的回答是:“佩佩的评论是正确的吗?”佩佩把引用的文本后面的句子删掉了:“在C++标准库中,声明(除了在C中定义为宏的名字)在内部。
#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;
}