1

ptrdiff_t当我遇到这个“问题”时,我正在使用和阅读 C++11 标准。首先,事实:

类型ptrdiff_t(只是一个示例)从标准 C 库头文件中提取<stddef.h><cstddef>(第 18.2/2 节)中。第 17.6.1.2 节告诉我们,从 C 标准库中提取的声明将位于std命名空间内:

但是,在 C++ 标准库中,声明(在 C 中定义为宏的名称除外)在 namespace 的命名空间范围 (3.3.6) 内stdstd未指定这些名称是否首先在全局命名空间范围内声明,然后通过显式使用声明(7.3.3)注入命名空间。

正如它还说的那样,声明可能首先在全局命名空间中声明,然后注入到std. 因此,对于我的实现来说,以下编译得很好是有道理的:

#include <cstddef>

int main(int argc, const char* argv[])
{
  std::ptrdiff_t x;
  ptrdiff_t y;
  return 0;
}

我的实现(gcc 4.6.3)必须ptrdiff_t在全局命名空间中声明,然后将其注入std. 但是,如果我编译以下代码,我会收到一个错误(注意<iostream>包含):

#include <iostream>

int main(int argc, const char* argv[])
{
  std::ptrdiff_t x;
  ptrdiff_t y;
  return 0;
}

main.cpp:在函数'int main(int,const char**)'中:
main.cpp:6:3:错误:'ptrdiff_t'未在此范围内声明
main.cpp:6:3:注意:建议的替代方案:
/usr/include/c++/4.6/i686-linux-gnu/./bits/c++config.h:156:28: 注意:'std::ptrdiff_t'</p>

因此,既然std::ptrdiff_t是可用的,<iostream>就必须<cstddef>以某种方式包含(尽管不是必需的)。但是为什么全球版本不像以前那样可用呢?即使它实际上是相同的标头,我是否不能期望这种注入是一致的?这似乎是奇怪的行为。是否发生注入可能未指定,但至少应该是一种方式或另一种方式,而不是两者,对吧?

4

2 回答 2

3

不要依赖一个包含另一个标题的标题,如果您想要在特定标题中声明/定义某些内容,则必须包含它。

对于您给出的示例,使用 g++ 实际上有两个定义ptrdiff_tsize_t就此而言)。第一个,在namespace std,来自<bits/c++config.h><stddef.h>以及来自(等)的全局命名空间中的一个<cstddef>

于 2012-12-17T04:51:11.960 回答
1

问题是您没有使用正确的标题。你应该做

     #include <cstddef>

反而。但是你使用

        #include<iostream>

这间接地定义了“std::ptrdiff_t”。但是,全局“::ptrdiff_t”没有在“iostream”中定义,并且“iostream”没有像你想象的那样包含“cstddef”。相反,“iostream”确实包含“bits/c++config.h”。实际的“std::ptrdiff_t”在该文件中定义。

如果您查看文件“cstddef”的内容,您会发现那里只有两个“有用”的行

顺便说一句,以上讨论适用于 GCC 4.6 和 GCC 4.7。对于 GCC 4.4,“iostream”间接包含“cstddef”,因此 ptrdiff_t 在两个命名空间(std 和全局)中都可用。#包括 #包括

后一行引入了全局“::ptrdiff_t”,前一行定义了 std 命名空间之一。

于 2013-08-16T21:35:26.883 回答