C++ "size_t"不需要"cstddef"标题?
C++ "size_t" doesn't need "cstddef" header?
我正在C++入门书中学习C++,它说"size_t"是在"cstddef"标题中定义的,但在这个练习中:
#include <iostream>
using namespace std;
int main()
{
int ar[10];
for (size_t x = 0; x < 10; ++x)
ar[x] = x;
for (auto a : ar)
cout << ar[a] << " ";
cout << endl;
return 0;
}
这不包括标头,Visual Studio 2017(和c ++ shell)编译程序没有错误。
size_t
实际上是一个灰色地带。std::size_t
是sizeof
的结果类型,但sizeof
是一个内置运算符,您可以在没有任何#include
的情况下使用。考虑这个完整的小程序:
// no includes, no using namespace std
int main()
{
auto x = sizeof(int); // x is std::size_t
}
最重要的是,Visual C++在这里的表现总是有点奇怪。即使在最新版本的编译器中使用/permissive- /std:c++latest
等设置,它仍然允许以下非法代码:
// no includes, no using namespace std
int main()
{
size_t i = 0;
}
事实上,它甚至允许这样做:
// no includes, no using namespace std
int main()
{
int ar[10];
for (size_t x = 0; x < 10; ++x)
ar[x] = x;
for (auto a : ar)
;
return 0;
}
尽管如此,其他人关于间接包含标题的说法是正确的。确切地说,C++标准在§20.5.5.2中对标准库标头有如下说明:
C++标头可能包含其他C++标头。
这意味着视觉C++无论如何都会在您的情况下正确运行。一旦你包含了<iostream>
,实现就可以自由地间接包含定义std::size_t
的六个标准C++头中的一个,而你的using namespace std;
(这是邪恶的)会完成其余的工作。
C++标准甚至保证了一些此类间接包含,但这不是其中之一,因此为了使您的代码与其他编译器兼容,强烈建议您包含<cstddef>
或其他保证std::size_t
之一。
允许标准标头包含其他标准标头。由于不同实现中的标头具有不同的依赖项,因此您仍应尝试显式包含所需的所有内容。例如,你的程序可能不会建立在Linux的libstdc++或macOS的libc++上。
标准标头通常会包含其他标准标头,因此在许多情况下,您可能会侥幸不包括正确的标头。
问题是标头之间的这种关系不在标准中,例如依赖于实现。如果未包含必需的标头,则代码可能适用于一个编译器,但可能会在另一个编译器上运行。
通常,如果您知道标头 X 中定义的内容在其定义中使用类型 T,则可能会认为在包含 X 后类型 T 将可用。例如,<vector>
使用std::size_t
作为std::vector
定义的一部分,因此它通常包括<cstddef>
。
有时可以使用前向声明来避免包含其他标准标头。但这只能通过类和结构来实现,而不是 typedef。
一些实现,例如GNU Libc,更加严格,并试图避免在内部包含标准标头。其他人,如MSVC,则不那么严格。与 GNU Libc 一起使用的代码通常适用于 MSVC。
很难验证您的代码是否包含您需要的所有内容。有一些工具可以帮助您找到缺少的包含,但使用多个编译器构建代码通常是查找这些问题的最佳方法。
不,std::size_t
可能在多个标头中定义:
Defined in header <cstddef>
Defined in header <cstdio>
Defined in header <cstdlib>
Defined in header <cstring>
Defined in header <ctime>
Defined in header <cwchar>
另请注意,<iostream>
本身包括其他标头。
首先,std::size_t
被定义为许多标准标头:<cstddef>
、<cstdio>
、<cstdlib>
、<cstring>
、<ctime>
和<cwchar>
。
如果不#include
其中之一,则不需要编译代码。
实际上,标准库的许多实现都有各种标准标头相互#include
,在这种情况下,您的代码将编译。 定义std::size_t
的标头(甚至它们的 C 标头等效项,如<stddef.h>
)包含在C++标准库中的其他标头中,这是很常见的,但不能保证。
更具体地说,标准库工作的许多部分都使用动态内存分配(标准容器、流缓冲区等)。 一个明显但不是必需的实现选择是它们使用size_t
来表示大小。 例如,像std::vector
这样的标准容器具有关联的size_type
,并且std::vector<any_type>::size_type
可以而且通常等同于std::size_t
。
<iostream>
(连同它自动#include
s的标头)不需要包含定义std::size_t
的标头,但 - 同样 - 标准中没有任何内容不允许它。
最后,这取决于您希望对可移植性保持谨慎程度。 如果<iostream>
引入了特定编译器的std::size_t
定义,则代码将编译。 编译器的未来版本可能会更新标准标头以更改它(尽管在实践中不太可能,但并非不可能)。 如果您打算将来将代码移植到另一个实现(编译器和标准库),则更有可能需要修改代码。
实际上,显式#include
ing<cstddef>
或任何其他定义std::size_t
的标头并没有什么坏处。 这样,使用std::size_t
的代码将进行编译,而不管其他标准标头在实现之间有何不同。
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 对于C++,方括号中的标题必须总是在引号中的标题之上吗
- 库标题在标题中不可见,但在 cmake build 下.cpp文件中完全可见.为什么?
- 为什么我不应该把所有东西都放在标题中?
- WinAPI 检查窗口是否具有常规标题栏
- 如何更改窗体上所有控件的标题?[C++生成器]
- 提升用于解析标题列的精神语法
- 所以我正在为我的学校作业练习继承,但我无法正确实施标题保护
- 如何删除已输入的书以及如何使标题,语言和名称在上面放置空格不会出错?
- 使用类 ?C++ 和 SFML 以及标题中的 15 个字符
- Gtkmm 窗口为空白,不显示任何小部件或标题
- 我将如何在 cpp 中生成一个随机且独特的标题
- std::带有颜色和标题的 clog 包装器无法正确打印整数
- 仅提升计时标题与链接
- 是否有理由在标题中保留完全专用的模板?
- 如何在QGroundControl的标题中放置空格?
- 崇高的林特与叮当在标题中找不到头文件
- C++ - 从 MFC 应用程序启动记事本,并将其默认标题从 "Untitled - Notepad" 更改为其他内容
- 无法在 GLFW 窗口标题中显示'ä'
- C++ "size_t"不需要"cstddef"标题?