简体   繁体   English

C ++“size_t”不需要“cstddef”头?

[英]C++ “size_t” doesn't need “cstddef” header?

I'm learning C++ with the book C++ Primer, and it says that "size_t" is defined in "cstddef" header, but in this exercise: 我正在学习使用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;
}

That doesn't have included the header, Visual Studio 2017 (and c++ shell) compiles the program without error. 这没有包含标题,Visual Studio 2017(和c ++ shell)编译程序时没有错误。

size_t is really a grey area. size_t实际上是一个灰色区域。 std::size_t is the result type of sizeof , but sizeof is a built-in operator you can use without any #include at all. std::size_tsizeof的结果类型,但sizeof是一个内置运算符,您可以在没有任何#include情况下使用它。 Consider this complete little program: 考虑这个完整的小程序:

// no includes, no using namespace std

int main()
{
    auto x = sizeof(int); // x is std::size_t
}

On top of that, Visual C++ has always behaved a bit strangely here. 最重要的是,Visual C ++在这里总是表现得有些奇怪。 Even with settings like /permissive- /std:c++latest in the newest version of the compiler, it still allows the following illegal code: 即使在最新版本的编译器中使用/permissive- /std:c++latest等设置,它仍然允许以下非法代码:

// no includes, no using namespace std

int main()
{
    size_t i  = 0;
}

In fact, it would even allow this : 事实上,它甚至会允许这样的

// 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;
}

Nevertheless, what others said about the indirect inclusion of headers is correct. 然而,其他人所说的间接包含标题是正确的。 To be precise, the C++ standard says the following about standard-library headers at §20.5.5.2: 确切地说,C ++标准在§20.5.5.2中说明了关于标准库头的以下内容:

A C++ header may include other C++ headers. C ++标头可能包含其他C ++标头。

Which means that Visual C++ behaves correctly in your case anyway. 这意味着无论如何,Visual C ++在您的情况下表现正常。 Once you include <iostream> , the implementation is free to indirectly include one of the six standard C++ headers that define std::size_t , and your using namespace std; 一旦你包含<iostream> ,实现可以自由地间接包括定义std::size_t六个标准C ++头之一 ,以及你的using namespace std; (which is evil) does the rest. (这是邪恶的)其余的。

The C++ standard even guarantees some of such indirect inclusions, but this isn't one of them, so in order to make your code compatible with other compilers, you are strongly encouraged to include <cstddef> or one of the others that guarantee std::size_t . C ++标准甚至保证了一些这样的间接包含,但这不是其中之一,所以为了使您的代码与其他编译器兼容,强烈建议您包含<cstddef>或其他保证std::size_t的其他内容std::size_t

Standard headers are allowed to include other standard headers. 标准标头允许包含其他标准标头。 Since headers in different implementations have different dependencies, you should still try to explicitly include everything that you need. 由于不同实现中的标头具有不同的依赖关系,因此您仍应尝试明确包含所需的所有内容。 It's possible that your program wouldn't build on Linux's libstdc++ or macOS's libc++, for instance. 例如,您的程序可能不会构建在Linux的libstdc ++或macOS的libc ++上。

Standard header will usually include other standard headers, so in many cases you might get away with not including proper ones. 标准标题通常包含其他标准标题,因此在许多情况下,您可能会因不包含正确标题而逃脱。

The problem is that such relations between headers are not in the standard eg depend on implementatation. 问题是标题之间的这种关系不在标准中,例如取决于实现。 If you don't include required headers, your code might work on one compiler, but might fail on another. 如果不包含必需的标头,则代码可能在一个编译器上运行,但在另一个编译器上可能会失败。

Usually if you know that something defined in header X uses type T in its definition, you might assume type T will be available after including X. For example <vector> uses std::size_t as part of std::vector definition, so it will usually include <cstddef> . 通常,如果你知道标题X中定义的东西在其定义中使用了类型T,你可能会假设类型T在包含X之后可用。例如, <vector>使用std::size_t作为std::vector定义的一部分,所以它通常包括<cstddef>

Sometimes forward declarations can be used to avoid including other standard headers. 有时可以使用前向声明来避免包含其他标准头。 But this is only possible with classes and structures, not typedefs. 但这只适用于类和结构,而不是typedef。

Some implementations, like GNU Libc for example, are more strict and try to avoid including standard headers internally. 某些实现(例如GNU Libc)更严格,并尝试避免在内部包含标准头。 Others, like MSVC, are less strict. 其他人,如MSVC,则不那么严格。 Code that works with GNU Libc will usually work with MSVC. 与GNU Libc一起使用的代码通常适用于MSVC。

It is hard to verify that your code includes everything you need. 很难验证您的代码是否包含您需要的所有内容。 There are tools that can help you find missing include's, but building your code with multiple compilers is usually the best way to find those issues. 有些工具可以帮助您找到缺少的包含,但使用多个编译器构建代码通常是找到这些问题的最佳方法。

Firstly, std::size_t is defined in a number of standard headers: <cstddef> , <cstdio> , <cstdlib> , <cstring> , <ctime> , and <cwchar> . 首先, std::size_t在许多标准头文件中定义: <cstddef><cstdio><cstdlib><cstring><ctime><cwchar>

Without #include ing one of these, your code is not required to compile. 如果没有#include其中一个,则不需要编译代码。

Practically, a lot of implementations of the standard library have various standard headers #include each other, in which case your code will compile. 实际上,标准库的许多实现都有各种标准头文件#include ,在这种情况下你的代码将被编译。 It is pretty common, but NOT guaranteed, for at least one of the headers that defines std::size_t (or even their C header equivalents like <stddef.h> ) to be included by other headers in the C++ standard library. 这是非常常见的,但不能保证,至少有一个标头定义了std::size_t (甚至它们的C标头等价,如<stddef.h> ),它们被C ++标准库中的其他标头包含在内。

More specifically, a lot of parts of the standard library work use dynamic memory allocation (standard containers, stream buffers, etc). 更具体地说,标准库工作的许多部分使用动态内存分配(标准容器,流缓冲区等)。 An obvious - but not required - implementation choice is that they use size_t to represent sizes. 一个明显但不是必需的实现选择是他们使用size_t来表示大小。 For example, standard containers like std::vector have an associated size_type , and std::vector<any_type>::size_type can be, and often is, equivalent to std::size_t . 例如,像std::vector这样的标准容器有一个关联的size_type ,而std::vector<any_type>::size_type可以,通常等同于std::size_t

<iostream> (along with headers it automatically #include s) is not required to include a header that defines std::size_t , but - equally - nothing in the standard disallows it. <iostream> (连同标题自动#include s)不需要包含定义std::size_t的标题,但是 - 同样 - 标准中的任何内容都不允许它。

In the end it comes down to how cautious you want to be concerning portability. 最后,它归结为您对可移植性的谨慎态度。 If <iostream> brings in a definition of std::size_t with your particular compiler, then your code will compile. 如果<iostream>使用您的特定编译器std::size_t的定义,那么您的代码将被编译。 It is possible (although unlikely in practice, not impossible) that a future release of your compiler will update the standard headers to change that. 有可能(虽然在实践中不太可能,但并非不可能),未来的编译器版本将更新标准头以更改它。 If you intend to port your code to another implementation (compiler and standard library) in future, there is a greater likelihood your code will need to be modified. 如果您打算将代码移植到另一个实现(编译器和标准库),则更有可能需要修改代码。

Practically, there is no harm by explicitly #include ing <cstddef> or any other header that defines std::size_t . 实际上,通过显式#include ing <cstddef>或任何其他定义std::size_t头文件没有任何危害。 That way, your code that uses std::size_t will compile, regardless of how other standard headers vary between implementations. 这样,使用std::size_t代码将编译,无论其他标准头如何在实现之间变化。

Nope, std::size_t might be defined in multiple headers: 不, 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>

Also note, that <iostream> itself includes other headers. 另请注意, <iostream>本身包含其他标头。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM