我正在学习使用C ++ Primer一书的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)编译程序时没有错误。
答案 0 :(得分:4)
size_t
实际上是一个灰色区域。 std::size_t
是[{1}}的结果类型,但sizeof
是一个内置运算符,您可以在没有任何sizeof
的情况下使用它。考虑这个完整的小程序:
#include
最重要的是,Visual C ++在这里总是表现得有些奇怪。即使在最新版本的编译器中使用// no includes, no using namespace std
int main()
{
auto x = sizeof(int); // x is std::size_t
}
之类的设置,它仍然允许以下非法代码:
/permissive- /std:c++latest
事实上,它甚至会允许这个:
// no includes, no using namespace std
int main()
{
size_t i = 0;
}
然而,其他人所说的间接包含标题是正确的。确切地说,C ++标准在§20.5.5.2中描述了以下关于标准库头的内容:
C ++标头可能包含其他C ++标头。
这意味着Visual C ++无论如何都会在您的情况下正常运行。一旦你加入// 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;
}
,实现就可以间接地包含six standard C++ headers that define std::size_t
中的一个,而你的<iostream>
(这是邪恶的)会完成其余的工作。
C ++标准甚至保证了一些这样的间接包含,但这不是其中之一,因此为了使您的代码与其他编译器兼容,强烈建议您包含using namespace std;
或其中一个保证<cstddef>
的其他人。
答案 1 :(得分:2)
允许标准标头包含其他标准标头。由于不同实现中的标头具有不同的依赖关系,因此您仍应尝试明确包含所需的所有内容。例如,您的程序可能不会构建在Linux的libstdc ++或macOS的libc ++上。
答案 2 :(得分:2)
标准标题通常会包含其他标准标题,因此在许多情况下,您可能会因为不包含正确的标题而离开。
问题是标题之间的这种关系不在标准中,例如取决于实施。如果您没有包含必需的标头,那么您的代码可能在一个编译器上运行,但在另一个编译器上可能会失败。
通常,如果你知道标题X中定义的东西在其定义中使用了类型T,你可能会假设类型T在包含X之后可用。例如<vector>
使用std::size_t
作为{{{1}的一部分1}}定义,因此它通常包含std::vector
。
有时可以使用前向声明来避免包含其他标准标头。但这只适用于类和结构,而不是typedef。
某些实现(例如GNU Libc)更严格,并尽量避免在内部包含标准头。其他人,如MSVC,则不那么严格。与GNU Libc一起使用的代码通常适用于MSVC。
很难验证您的代码是否包含您需要的所有内容。有些工具可以帮助您找到遗漏的内容,但使用多个编译器构建代码通常是找到这些问题的最佳方式。
答案 3 :(得分:2)
首先,std::size_t
在多个标准标题中定义:<cstddef>
,<cstdio>
,<cstdlib>
,<cstring>
,<ctime>
和<cwchar>
。
如果没有#include
其中一个,则不需要编译代码。
实际上,标准库的许多实现都有各种标准头#include
,在这种情况下你的代码将被编译。这是非常常见的,但不能保证,至少有一个标头定义std::size_t
(甚至它们的C标头等价物,如<stddef.h>
)将被C ++标准库中的其他标头包含。< / p>
更具体地说,标准库工作的很多部分都使用动态内存分配(标准容器,流缓冲区等)。一个明显但不是必需的实现选择是他们使用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
<cstddef>
或任何其他定义std::size_t
的标头都没有任何危害。这样,使用std::size_t
的代码将进行编译,无论其他标准标头在实现之间如何变化。
答案 4 :(得分:1)
不,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>
本身包含其他标题。