为什么我不应该#include

发布于 2025-01-15 18:25:55 字数 161 浏览 4 评论 0 原文

我用我的代码发布了一个问题,其唯一的 #include 指令如下:

#include <bits/stdc++.h>

我的老师告诉我这样做,但在评论部分我被告知我不应该这样做。

为什么?

I posted a question with my code whose only #include directive was the following:

#include <bits/stdc++.h>

My teacher told me to do this, but in the comments section I was informed that I shouldn't.

Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

转瞬即逝 2025-01-22 18:25:55

包含 似乎在 Stack Overflow 上越来越常见,也许是本学年国家课程中新添加的内容。

我想这样的优点是模糊的:

  • 你只需要写一个 #include 行。
  • 您不需要查找所有内容都位于哪个标准标头中。

不幸的是,这是一个懒惰的黑客,直接命名 GCC 内部标头而不是单独的标准标头,例如 < ;iostream>。它破坏了便携性并养成了可怕的习惯。

缺点包括:

  • 它可能只适用于该编译器。
  • 当你使用它时,你不知道它会做什么,因为它的内容不是由标准设定的。
  • 即使只是将编译器升级到其自己的下一个版本也可能会破坏您的程序。
  • 每个标准头都必须与源代码一起解析和编译,这很慢,并且会在某些编译设置下产生庞大的可执行文件。

不要这样做!


更多信息:

原因示例:

Including <bits/stdc++.h> appears to be an increasingly common thing to see on Stack Overflow, perhaps something newly added to a national curriculum in the current academic year.

I imagine the advantages are vaguely given thus:

  • You only need write one #include line.
  • You do not need to look up which standard header everything is in.

Unfortunately, this is a lazy hack, naming a GCC internal header directly instead of individual standard headers like <string>, <iostream> and <vector>. It ruins portability and fosters terrible habits.

The disadvantages include:

  • It will probably only work on that compiler.
  • You have no idea what it'll do when you use it, because its contents are not set by a standard.
  • Even just upgrading your compiler to its own next version may break your program.
  • Every single standard header must be parsed and compiled along with your source code, which is slow and results in a bulky executable under certain compilation settings.

Don't do it!


More information:

Example of why Quora is bad:

丑疤怪 2025-01-22 18:25:55

为什么?因为它的使用方式就好像它应该是 C++ 标准头一样,但没有标准提及它。所以你的代码在构造上是不可移植的。您在 cppreference 上找不到任何相关文档。所以它也可能不存在。这是某人的想象:)

我发现——令我恐惧和难以置信——有一个著名的教程网站,其中每个 C++ 示例似乎都包含此标头。世界疯了。这就是证据。


致任何编写此类“教程”的人

请停止使用此标题。忘记它吧。不要传播这种疯狂。如果您不愿意理解为什么这样做是错误,请相信我的话。我根本不喜欢被视为任何事情上的权威人物,而且我可能有一半的时间都充满这种感觉,但我只会在这一种情况下破例。我声称我知道我在这里在说什么。请相信我的话。我恳求你。

PS我完全可以想象这种邪恶想法可能发生的可恶的“教学标准”,以及导致它的情况。仅仅因为似乎有实际需要,并不意味着它是可以接受的——即使现在回想起来也是如此。

PPS 不,没有实际需要。 C++ 标准头文件并不多,而且有详细的文档记录。如果你教书,你就会通过添加这样的“魔法”来伤害你的学生。培养具有神奇心态的程序员是我们最不想要的。如果您需要向学生提供 C++ 的子集以使他们的生活更轻松,只需制作一份讲义,其中包含适用于您教授的课程的简短标题列表,以及您希望学生使用的库结构的简明文档。

Why? Because it is used as if it were supposed to be a C++ standard header, but no standard mentions it. So your code is non-portable by construction. You won't find any documentation for it on cppreference. So it might as well not exist. It's a figment of someone's imagination :)

I have discovered - to my horror and disbelief - that there is a well-known tutorial site where every C++ example seems to include this header. The world is mad. That's the proof.


To anyone writing such "tutorials"

Please stop using this header. Forget about it. Don't propagate this insanity. If you're unwilling to understand why doing this is Wrong, take my word for it. I'm not OK being treated as a figure of authority on anything at all, and I'm probably full of it half the time, but I'll make an exception in this one case only. I claim that I know what I'm talking about here. Take me on my word. I implore you.

P.S. I can well imagine the abominable "teaching standard" where this wicked idea might have taken place, and the circumstances that led to it. Just because there seemed to be a practical need for it doesn't make it acceptable - not even in retrospect.

P.P.S. No, there was no practical need for it. There aren't that many C++ standard headers, and they are well documented. If you teach, you're doing your students a disservice by adding such "magic". Producing programmers with a magical mindset is the last thing we want. If you need to offer students a subset of C++ to make their life easier, just produce a handout with the short list of headers applicable to the course you teach, and with concise documentation for the library constructs you expect the students to use.

旧时模样 2025-01-22 18:25:55

有一个名为 Programming Puzzles & 的 Stack Exchange 网站。代码高尔夫。该网站上的编程难题符合难题的定义:

一种玩具、问题或其他装置,旨在通过提出需要通过独创性或耐心的努力来解决的困难来娱乐。

它们的设计目的是为了娱乐,而不是像一个正在工作的程序员可能会被日常工作中遇到的现实问题所娱乐的那样。

Code Golf 是“一种休闲计算机编程竞赛,参与者力求获得尽可能短的资源实现某种算法的代码。”在 PP&CG 网站的答案中,您会看到人们在答案中指定了字节数。当他们找到一种方法来减少一些字节时,他们会删除原始数字并记录新数字。

正如您所料,代码高尔夫会奖励极端的编程语言滥用。单字母变量名。没有空格。创造性地使用库函数。未记录的功能。非标准编程实践。令人震惊的黑客行为。

如果程序员在工作中提交了包含高尔夫风格代码的拉取请求,它将被拒绝。他们的同事会嘲笑他们。他们的经理会顺便到他们的办公桌旁聊天。即便如此,程序员们还是通过向 PP&CG 提交答案来取乐。

这与 stdc++.h 有什么关系?正如其他人指出的那样,使用它是懒惰的。它是不可移植的,因此您不知道它是否适用于您的编译器或下一个版本的编译器。它会养成坏习惯。它是非标准的,因此您的程序的行为可能与您的预期不同。它可能会增加编译时间和可执行文件大小。

这些都是有效且正确的反对意见。那么为什么有人会使用这个怪物呢?

事实证明,有些人喜欢没有代码高尔夫编程难题。他们聚集在一起,在 ACM-ICPC、Google Code Jam 和 Facebook Hacker Cup 等活动中,或者在 Topcoder 和 Codeforces 等网站上进行竞争。他们的排名取决于程序的正确性、执行速度以及提交解决方案的速度。为了最大限度地提高执行速度,许多参与者使用 C++。为了最大限度地提高编码速度,其中一些使用 stdc++.h

这是个好主意吗?让我们检查一下缺点。可移植性?这并不重要,因为这些编码活动使用参赛者事先知道的特定编译器版本。符合标准吗?与使用寿命小于一小时的代码块无关。编译时间和可执行文件大小?这些不是比赛评分标准的一部分。

所以我们留下了坏习惯。这是一个有效的反对意见。通过使用此头文件,参赛者可以避免了解哪个标准头文件定义了他们在程序中使用的功能。当他们编写实际代码(而不是使用 stdc++.h)时,他们将不得不花时间查找这些信息,这意味着他们的工作效率会降低。这就是使用 stdc++.h 进行练习的缺点。

这就提出了一个问题:如果竞争性编程鼓励了使用 stdc++.h 和违反其他编码标准等坏习惯,那么为什么值得参加竞争性编程呢?一个答案是,人们这样做的原因与他们在 PP&CG 上发布程序的原因相同:一些程序员发现在类似游戏的环境中使用他们的编码技能很有趣。

因此,是否使用 stdc++.h 的问题归结为编程竞赛中编码速度的好处是否超过了使用它可能养成的坏习惯。

这个问题问:“为什么我不应该#include ?”我意识到提出这个问题并回答这个问题是为了表明一个观点,并且接受的答案旨在成为该问题的唯一正确答案。但问题不是“为什么我不应该在生产代码中#include ?”因此,我认为考虑答案可能不同的其他场景是合理的。

There's a Stack Exchange site called Programming Puzzles & Code Golf. The programming puzzles on that site fit this definition of puzzle:

a toy, problem, or other contrivance designed to amuse by presenting difficulties to be solved by ingenuity or patient effort.

They are designed to amuse, and not in the way that a working programmer might be amused by a real-world problem encountered in their daily work.

Code Golf is "a type of recreational computer programming competition in which participants strive to achieve the shortest possible source code that implements a certain algorithm." In the answers on the PP&CG site, you'll see people specify the number of bytes in their answers. When they find a way to shave off a few bytes, they'll strike out the original number and record the new one.

As you might expect, code golfing rewards extreme programming language abuse. One-letter variable names. No whitespace. Creative use of library functions. Undocumented features. Nonstandard programming practices. Appalling hacks.

If a programmer submitted a pull request at work containing golf-style code, it would be rejected. Their co-workers would laugh at them. Their manager would drop by their desk for a chat. Even so, programmers amuse themselves by submitting answers to PP&CG.

What does this have to do with stdc++.h? As others have pointed out, using it is lazy. It's non-portable, so you don't know if it will work on your compiler or the next version of your compiler. It fosters bad habits. It's non-standard, so your program's behavior may differ from what you expect. It may increase compile time and executable size.

These are all valid and correct objections. So why would anyone use this monstrosity?

It turns out that some people like programming puzzles without the code golf. They get together and compete at events like ACM-ICPC, Google Code Jam, and Facebook Hacker Cup, or on sites like Topcoder and Codeforces. Their rank is based on program correctness, execution speed, and how fast they submit a solution. To maximize execution speed, many participants use C++. To maximize coding speed, some of them use stdc++.h.

Is this is a good idea? Let's check the list of disadvantages. Portability? It doesn't matter since these coding events use a specific compiler version that contestants know in advance. Standards compliance? Not relevant for a block of code whose useful life is less than one hour. Compile time and executable size? These aren't part of the contest's scoring rubric.

So we're left with bad habits. This is a valid objection. By using this header file, contestants are avoiding the chance to learn which standard header file defines the functionality they're using in their program. When they're writing real-world code (and not using stdc++.h) they'll have to spend time looking up this information, which means they'll be less productive. That's the downside of practicing with stdc++.h.

This raises the question of why it's worth taking part in competitive programming at all if it encourages bad habits like using stdc++.h and violating other coding standards. One answer is that people do it for the same reason they post programs on PP&CG: some programmers find it enjoyable to use their coding skills in a game-like context.

So the question of whether to use stdc++.h comes down to whether the coding speed benefits in a programming contest outweigh the bad habits that one might develop by using it.

This question asks: "Why should I not #include <bits/stdc++.h>?" I realize that it was asked and answered to make a point, and the accepted answer is intended to be the One True Answer to this question. But the question isn't "Why should I not #include <bits/stdc++.h> in production code?" Therefore, I think it's reasonable to consider other scenarios where the answer may be different.

じее 2025-01-22 18:25:55

来自 N4606,工作草案,编程语言 C++ 标准:

17.6.1.2 标头 [headers]

  1. C++ 标准库的每个元素都在标头中声明或定义(视情况而定)。

  2. C++ 标准库提供了 61 个 C++ 库头文件,如表 14 所示。

表 14 — C++ 库头文件

<算法>; <未来> <数字> 
<任意> <初始化列表> <可选> <系统错误>
<数组>   <线程>
<原子>  <队列> <元组>
<位集>  <随机> <类型特征>
<计时>  <比例> <类型索引>
<编解码>  <正则表达式> <类型信息>
<复杂> <迭代器> <范围分配器> ;
<条件变量> <限制> <设置> <无序集>
<双端队列> <列表> <共享互斥体> <实用程序>
<例外> <区域设置> <流> 
<执行> <地图> <堆栈> <变体>
<文件系统> <内存> <标准例外> <矢量>
<转发列表> <内存资源> <流缓冲>
 <互斥体> <字符串>
<功能性> <新> <字符串视图>

没有 头文件。那里。这并不奇怪,因为标头是实现细节,通常带有警告:

  • 这是一个内部头文件,包含在其他库头文件中。
  • 请勿尝试直接使用它。

<位/stdc++.h>还带有警告:

  • 这是预编译头的实现文件。

From N4606, Working Draft, Standard for Programming Language C++ :

17.6.1.2 Headers [headers]

  1. Each element of the C++ standard library is declared or defined (as appropriate) in a header.

  2. The C++ standard library provides 61 C++ library headers, as shown in Table 14.

Table 14 — C++ library headers

<algorithm> <future> <numeric> <strstream>
<any> <initializer_list> <optional> <system_error>
<array> <iomanip> <ostream> <thread>
<atomic> <ios> <queue> <tuple>
<bitset> <iosfwd> <random> <type_traits>
<chrono> <iostream> <ratio> <typeindex>
<codecvt> <istream> <regex> <typeinfo>
<complex> <iterator> <scoped_allocator> <unordered_map>
<condition_variable> <limits> <set> <unordered_set>
<deque> <list> <shared_mutex> <utility>
<exception> <locale> <sstream> <valarray>
<execution> <map> <stack> <variant>
<filesystem> <memory> <stdexcept> <vector>
<forward_list> <memory_resorce> <streambuf>
<fstream> <mutex> <string>
<functional> <new> <string_view>

There's no <bits/stdc++.h> there. This is not surprising, since <bits/...> headers are implementation detail, and usually carry a warning:

  • This is an internal header file, included by other library headers.
  • Do not attempt to use it directly.

<bits/stdc++.h> also carries a warning:

  • This is an implementation file for a precompiled header.
平生欢 2025-01-22 18:25:55

我至少喜欢通过查看这个头文件来看到可以包含的所有头文件的列表,以及它们属于哪个版本的 C++。在这方面它确实很有用。

包含 真的有多糟糕吗?

我想查看一些真实数据 - 一些用于比较编译时间二进制可执行文件大小的数字。因此,这是一个快速的“hello world”比较测试。

注意:要了解 头文件的位置以及其中的内容,请直接跳至底部标题为“ 在哪里以及什么?”的部分。

摘要:

包含 “包含所有标头”标头很容易,但编译速度相对较慢。

包含 头文件与 GCC/g++ 编译器一起工作正常(大概是 LLVM Clang 编译器也是如此,因为它们的目标是与 GCC 兼容),并且

  1. 在二进制可执行文件大小上没有区别,但
  2. 编译时间最多4倍!

我的测试

这是一个示例 C++ 程序:

include_bits_stdc++.cpp

// We will test including this header vs NOT including this header
#include <bits/stdc++.h>

#include <iostream>  // For `std::cin`, `std::cout`, `std::endl`, etc.

int main()
{
    printf("Hello ");
    std::cout << "world!\n\n";

    return 0;
}

以下是一些构建和运行命令:

# make a bin directory
mkdir -p bin

# compile, timing how long it takes
time g++ -Wall -Wextra -Werror -O3 -std=c++17 include_bits_stdc++.cpp -o bin/a

# check binary executable size
size bin/a

# run
bin/a

WithOUT #include at 如果我按原样

运行上面的“compile”命令,我会看到以下 10 个编译时间:

real    0m0.362s
real    0m0.372s
real    0m0.502s
real    0m0.383s
real    0m0.367s
real    0m0.283s
real    0m0.294s
real    0m0.281s
real    0m0.292s
real    0m0.276s

平均编译时间: (0.362 + 0.372 + 0.502 + 0.383 + 0.367 + 0.283 + 0.294 + 0.281 + 0.292 + 0.276)/10 = 0.3412

size bin/a 显示:

text    data     bss     dec     hex filename
2142     656     280    3078     c06 bin/a

WITH #include 位于前

10 个编译时间:

real    0m1.398s
real    0m1.006s
real    0m0.952s
real    0m1.331s
real    0m1.549s
real    0m1.454s
real    0m1.417s
real    0m1.541s
real    0m1.546s
real    0m1.558s

平均编译时间: <代码>(1.398 + 1.006 + 0.952 + 1.331 + 1.549 + 1.454 + 1.417 + 1.541 + 1.546 + 1.558)/10 = 1.3752

size bin/a 显示:

text    data     bss     dec     hex filename
2142     656     280    3078     c06 bin/a

结论

因此,包含标头可以在 gcc/g++ 编译器中正常工作,并且使二进制可执行文件大小没有差异,但需要 1.3752 秒/ 0.3412 秒 = 编译时间延长 4 倍!

位于何处、是什么?

摘要

头文件作为 gcc/g++ 编译器的一部分包含在内。

您可以使用以下命令在 Linux(例如:Ubuntu)系统上找到它:

find /usr/include -ipath "*bits/stdc++.h*"

上面的命令几乎是即时的。但是,如果没有找到任何内容,您可以像这样搜索整个文件系统,这将花费更长的时间:

# Option 1: showing read permissions errors
find / -ipath "*bits/stdc++.h*"

# Option 2 (preferred): hiding read permissions (stderr, file descriptor 2)
# errors
find / -ipath "*bits/stdc++.h*" 2>/dev/null

如果在 Linux Ubuntu 上, bits/stdc++.h> 将位于您的本地系统上:

  1. 在 Ubuntu 18.04 上,使用 GCC 8: /usr/include/x86_64-linux-gnu/c++/8/bits/stdc++.h
  2. 在 Ubuntu 22.04 上,使用 GCC 11: /usr/include/x86_64-linux-gnu/c++ /11/bits/stdc++.h

这里可以直接在线查看gcc源代码中的文件:gcc/ libstdc++-v3/include/precompiled/stdc++.h

我至少喜欢看到可以包含的所有标头的列表,以及它们的 C++ 版本属于,通过查看该头文件。在这方面,它确实很有用。

详细信息

如果您在具有出色索引器的 IDE 中打开上面的代码,例如 Eclipse(它具有我发现的最好的索引器;它的索引要好得多< /em> 而非 MS VSCode),并且在 #include 行上Ctrl + 单击,则会跳转直接到您系统上的那个头文件!在 Linux Ubuntu 上,它直接跳转到此路径并打开此文件:/usr/include/x86_64-linux-gnu/c++/8/bits/stdc++.h

您可以直接在 gcc 源代码中查看该文件的最新版本,此处: gcc/libstdc++-v3/include/precompiled/stdc++.h它只是一个头文件,包含所有其他头文件!这非常有用且富有洞察力,只需在一个位置查看所有头文件即可了解它们的内容是什么以及它们包括什么!同样,在 Eclipse 中,您可以轻松地 Ctrl + Click 每个包含的头文件直接跳转到其源代码实现。

以下是 gcc 编译器附带的完整、最新的 头文件。如果您想将其包含在您自己的个人项目中或与其他编译器一起使用,您始终可以复制并粘贴此内容并自行创建此文件。

gcc/libstdc++-v3/include/precompiled/stdc++.h

// C++ includes used for precompiling -*- C++ -*-

// Copyright (C) 2003-2024 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file stdc++.h
 *  This is an implementation file for a precompiled header.
 */

// 17.4.1.2 Headers

// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <csetjmp>
#include <cstdarg>
#include <cstddef>
#include <cstdlib>

#if __cplusplus >= 201103L
#include <cstdint>
#endif

// C++
// #include <bitset>
// #include <complex>
#include <algorithm>
#include <bitset>
#include <functional>
#include <iterator>
#include <limits>
#include <memory>
#include <new>
#include <numeric>
#include <typeinfo>
#include <utility>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <initializer_list>
#include <ratio>
#include <scoped_allocator>
#include <tuple>
#include <typeindex>
#include <type_traits>
#endif

#if __cplusplus >= 201402L
#endif

#if __cplusplus >= 201703L
#include <any>
// #include <execution>
#include <optional>
#include <variant>
#include <string_view>
#endif

#if __cplusplus >= 202002L
#include <bit>
#include <compare>
#include <concepts>
#include <numbers>
#include <ranges>
#include <span>
#include <source_location>
#include <version>
#endif

#if __cplusplus > 202002L
#include <expected>
#include <stdatomic.h>
#if __cpp_impl_coroutine
# include <coroutine>
#endif
#endif

#if _GLIBCXX_HOSTED
// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cwchar>
#include <cwctype>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdalign>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cuchar>
#endif

// C++
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <codecvt>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif

#if __cplusplus >= 201402L
#include <shared_mutex>
#endif

#if __cplusplus >= 201703L
#include <any>
#include <charconv>
// #include <execution>
#include <filesystem>
#include <optional>
#include <memory_resource>
#include <variant>
#endif

#if __cplusplus >= 202002L
#include <barrier>
#include <bit>
#include <compare>
#include <concepts>
#include <format>
#include <latch>
#include <numbers>
#include <ranges>
#include <span>
#include <stop_token>
#include <semaphore>
#include <source_location>
#include <syncstream>
#include <version>
#endif

#if __cplusplus > 202002L
#include <expected>
#include <generator>
#include <print>
#include <spanstream>
#if __has_include(<stacktrace>)
# include <stacktrace>
#endif
#include <stdatomic.h>
#include <stdfloat>
#endif

#if __cplusplus > 202302L
#include <text_encoding>
#endif

#endif // HOSTED

另请参阅

  1. https://www.geeksforgeeks.org/bitsstdc-hc/
  2. [我的问题和答案]答案] 了解 sizetextdatabssdec 的含义> 输出:
    1. 电气工程堆栈交换:如何在编译时找出 STM32 的闪存和动态存储器(SRAM)有多少)用完了吗?
    2. 将 binutils size 输出从“sysv”格式转换 (size --format=sysv my_executable )转换为“berkeley”格式(size --format=berkeley my_executable

I at least like seeing a list of all headers one can include, and which version of C++ they pertain to, by looking at this header file. It is really useful in that regard.

How bad is including <bits/stdc++.h>, really?

I wanted to see some real data--some numbers to compare compile time and binary executable size. So, here is a quick "hello world" comparison test.

Note: to learn where is the <bits/stdc++.h> header file, and what is in it, jump straight down to the section at the bottom titled "Where and what is <bits/stdc++.h>?".

Summary:

Including the <bits/stdc++.h> "include all headers" header is easy, but comparatively slow to compile.

Including the <bits/stdc++.h> header file works fine with the GCC/g++ compiler (and presumably the LLVM Clang compiler too, since they aim to be GCC-compatible), and

  1. makes no difference on binary executable size, but
  2. it takes up to 4x longer to compile!

My testing

Here is a sample C++ program:

include_bits_stdc++.cpp:

// We will test including this header vs NOT including this header
#include <bits/stdc++.h>

#include <iostream>  // For `std::cin`, `std::cout`, `std::endl`, etc.

int main()
{
    printf("Hello ");
    std::cout << "world!\n\n";

    return 0;
}

Here are some build and run commands:

# make a bin directory
mkdir -p bin

# compile, timing how long it takes
time g++ -Wall -Wextra -Werror -O3 -std=c++17 include_bits_stdc++.cpp -o bin/a

# check binary executable size
size bin/a

# run
bin/a

WithOUT #include <bits/stdc++.h> at the top

If I run the "compile" command above with the code as-is, here are 10 compile times I see:

real    0m0.362s
real    0m0.372s
real    0m0.502s
real    0m0.383s
real    0m0.367s
real    0m0.283s
real    0m0.294s
real    0m0.281s
real    0m0.292s
real    0m0.276s

Average compile time: (0.362 + 0.372 + 0.502 + 0.383 + 0.367 + 0.283 + 0.294 + 0.281 + 0.292 + 0.276)/10 = 0.3412 seconds.

size bin/a shows:

text    data     bss     dec     hex filename
2142     656     280    3078     c06 bin/a

WITH #include <bits/stdc++.h> at the top

10 compile times:

real    0m1.398s
real    0m1.006s
real    0m0.952s
real    0m1.331s
real    0m1.549s
real    0m1.454s
real    0m1.417s
real    0m1.541s
real    0m1.546s
real    0m1.558s

Average compile time: (1.398 + 1.006 + 0.952 + 1.331 + 1.549 + 1.454 + 1.417 + 1.541 + 1.546 + 1.558)/10 = 1.3752 seconds.

size bin/a shows:

text    data     bss     dec     hex filename
2142     656     280    3078     c06 bin/a

Conclusions

So, including the header works fine with the gcc/g++ compiler, and makes no difference on binary executable size, but it takes 1.3752 sec / 0.3412 sec = 4x longer to compile!

Where and what is <bits/stdc++.h>?

Summary

The <bits/stdc++.h> header file is included as part of the gcc/g++ compiler.

You can find it on your Linux (ex: Ubuntu) system with this command:

find /usr/include -ipath "*bits/stdc++.h*"

The above command is almost instant. But, if it doesn't find anything, you can search your entire file system like this, which will take much longer:

# Option 1: showing read permissions errors
find / -ipath "*bits/stdc++.h*"

# Option 2 (preferred): hiding read permissions (stderr, file descriptor 2)
# errors
find / -ipath "*bits/stdc++.h*" 2>/dev/null

If on Linux Ubuntu, <bits/stdc++.h> will be located on your local system at:

  1. On Ubuntu 18.04, with GCC 8: /usr/include/x86_64-linux-gnu/c++/8/bits/stdc++.h
  2. On Ubuntu 22.04, with GCC 11: /usr/include/x86_64-linux-gnu/c++/11/bits/stdc++.h

You can view the file in the gcc source code directly online here: gcc/libstdc++-v3/include/precompiled/stdc++.h

I at least like seeing a list of all headers one can include, and which version of C++ they pertain to, by looking at that header file. It is really useful in that regard.

Details

If you open the code above in an IDE with a great indexer, such as Eclipse (which has the best indexer I've ever found; it indexes far better than MS VSCode), and Ctrl + Click on the #include <bits/stdc++.h> line, it will jump straight to that header file on your system! On Linux Ubuntu, it jumps straight to this path and opens this file: /usr/include/x86_64-linux-gnu/c++/8/bits/stdc++.h.

You can view the latest version of this file in the gcc source code directly, here: gcc/libstdc++-v3/include/precompiled/stdc++.h. It is simply a header file which includes all other header files! This is really useful and insightful to just look at all header files in one place to get a feel for what they are and what they include! And again, in Eclipse, you can easily Ctrl + Click on each included header file to jump right to its source code implementation.

Here is the full, latest <bits/stdc++.h> header file included with the gcc compiler. You can always copy and paste this content and create this file yourself if you want to include it in your own personal project or use it with another compiler.

gcc/libstdc++-v3/include/precompiled/stdc++.h:

// C++ includes used for precompiling -*- C++ -*-

// Copyright (C) 2003-2024 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file stdc++.h
 *  This is an implementation file for a precompiled header.
 */

// 17.4.1.2 Headers

// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <csetjmp>
#include <cstdarg>
#include <cstddef>
#include <cstdlib>

#if __cplusplus >= 201103L
#include <cstdint>
#endif

// C++
// #include <bitset>
// #include <complex>
#include <algorithm>
#include <bitset>
#include <functional>
#include <iterator>
#include <limits>
#include <memory>
#include <new>
#include <numeric>
#include <typeinfo>
#include <utility>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <initializer_list>
#include <ratio>
#include <scoped_allocator>
#include <tuple>
#include <typeindex>
#include <type_traits>
#endif

#if __cplusplus >= 201402L
#endif

#if __cplusplus >= 201703L
#include <any>
// #include <execution>
#include <optional>
#include <variant>
#include <string_view>
#endif

#if __cplusplus >= 202002L
#include <bit>
#include <compare>
#include <concepts>
#include <numbers>
#include <ranges>
#include <span>
#include <source_location>
#include <version>
#endif

#if __cplusplus > 202002L
#include <expected>
#include <stdatomic.h>
#if __cpp_impl_coroutine
# include <coroutine>
#endif
#endif

#if _GLIBCXX_HOSTED
// C
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cwchar>
#include <cwctype>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdalign>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cuchar>
#endif

// C++
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <codecvt>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif

#if __cplusplus >= 201402L
#include <shared_mutex>
#endif

#if __cplusplus >= 201703L
#include <any>
#include <charconv>
// #include <execution>
#include <filesystem>
#include <optional>
#include <memory_resource>
#include <variant>
#endif

#if __cplusplus >= 202002L
#include <barrier>
#include <bit>
#include <compare>
#include <concepts>
#include <format>
#include <latch>
#include <numbers>
#include <ranges>
#include <span>
#include <stop_token>
#include <semaphore>
#include <source_location>
#include <syncstream>
#include <version>
#endif

#if __cplusplus > 202002L
#include <expected>
#include <generator>
#include <print>
#include <spanstream>
#if __has_include(<stacktrace>)
# include <stacktrace>
#endif
#include <stdatomic.h>
#include <stdfloat>
#endif

#if __cplusplus > 202302L
#include <text_encoding>
#endif

#endif // HOSTED

See also

  1. https://www.geeksforgeeks.org/bitsstdc-h-c/
  2. [my Questions & Answers] learn what text, data, bss, and dec mean in the size output:
    1. Electrical Engineering Stack Exchange: How do I find out at compile time how much of an STM32's Flash memory and dynamic memory (SRAM) is used up?
    2. Convert binutils size output from "sysv" format (size --format=sysv my_executable) to "berkeley" format (size --format=berkeley my_executable)
一世旳自豪 2025-01-22 18:25:55

我们不使用:的原因

#include <bits/stdc++.h>

是因为效率。
我打个比方:
对于那些了解 Java 的人:
如果你问你的导师以下内容是否是一个好主意,除非他们是一个糟糕的导师,否则他们会说不:

import java.*.*

#include... 基本上做同样的事情... 这不是不使用它的唯一原因,但是这是不使用它的主要原因之一。
对于现实生活中的类比:
想象一下,你有一个图书馆,你想从图书馆借几本书,你会把整个图书馆搬到你家旁边吗?这将是昂贵且低效的。如果你只需要 5 本书,那么只取出 5 本书......而不是整个图书馆......

#include <bits/stdc++.h>

看起来程序很方便,我只需要输入一个包含语句,它就可以工作,与移动整个图书馆是一样的,看我只需要搬一整个图书馆而不是一本一本地搬五本书。对你来说看起来很方便,也就是说,对于真正需要搬家的人来说?没那么多,猜猜在 C++ 中,进行移动的人将是您的计算机...计算机不会喜欢为您编写的每个源文件移动整个库:).....

The reason we do not use:

#include <bits/stdc++.h>

is because of effiency.
Let me make an analogy:
For those of you who know Java:
If you asked your instructor if the following was a good idea, unless they are a bad instructor they would say no:

import java.*.*

The #include... thing does the same thing basically... That's not the only reason not to use it, but it is one of the major reasons not to use it.
For a real life analogy:
Imagine you had a library and you wanted to borrow a couple of books from the library, would you relocate the entire library next to your house?? It would be expensive and ineffiecient. If you only need 5 books, well then only take out 5... Not the whole library.....

#include <bits/stdc++.h>

Looks convienent to the program look I only need to type one include statement and it works, same thing with moving a whole library, look I only need to move one whole library instead of 5 books, one by one. Looks convienent to you that is, for the person who actually has to do the moving?? Not so much, and guess what in C++ the person doing the moving will be your computer... The computer will not enjoy moving the entire library for every source file you write :).....

俯瞰星空 2025-01-22 18:25:55

如果您的老师是 ICPC 教练,那么他/她是对的,但如果您的老师是软件工程师可能不是。

两者都有优点和缺点:

优点

  • 使用它可以节省编码时间
  • 您无需费力记住哪个标头包含什么内容
  • 如果您有源代码限制(通常是 ICPC 风格的限制)有)并且您想挤入尽可能多的行,那么它可能会派上用场。

缺点

  • 但它增加了编译时间。
  • 由于它包含大量命名空间,因此您可能会意外地遇到难以调试的问题。

If your teacher is an ICPC coach then he/she is right, but if your teacher is a software engineer probably he/she is not.

There are pros and cons of both:

pros:

  • Using it saves coding time
  • You don't need to take the pain of remembering which header contains what
  • If you have a source code limit(which ICPC style contests generally have) and you want to squeeze in as many lines as possible then it might come handy.

cons:

  • But it increases compile time.
  • Since it includes lots of namespaces, you may accidentally get into issues which might be hard to debug.
时光匆匆的小流年 2025-01-22 18:25:55

对我来说最大的问题是包含这个头文件将无法编译。因此,如果它存在,我必须将其删除,尝试编译并添加所需的标准头文件。

The biggest problem for me is that including this header file won’t compile. So if it’s there, I’ll have to remove it, try to compile, and add the standard header files that are needed.

指尖上的星空 2025-01-22 18:25:55

我的第一个想法是,bits/stdc++.h 似乎确实是 GNU libstdc++ 的内部实现细节标头。因此,决不应该直接从 C++ 程序源中包含它。

这是基于一致的观察,即在 GNU/linux 上,名为 bits 的子目录最有可能是 GNU libc 和 GNU libstdc++ 放置其内部私有头文件的常规位置。此类标头包含实现细节,并且不能保证它们的存在在补丁编译器版本之间保持稳定。

看一下/usr/include/x86_64-linux-gnu/bits/下的glibc头文件,几乎都禁止使用#error直接包含指令。

类似地,对于 GNU libstdc++ 标头;这些位于 /usr/include/c++/12/bits//usr/include/x86_64-linux-gnu/c++/12/bits/ 下(几乎)它们都在开头都有文档注释,例如:

/** @file bits/atomic_wait.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{atomic}
 */

在某些 bits 子目录下进行 Grepping 似乎表明该目录确实是为实现保留的。假设 gcc 版本为 12,在 x86_64 架构上,尝试以下命令:

$ grep "Never include" /usr/include/x86_64-linux-gnu/bits/*.h
$ grep "Do not attempt to use it directly" /usr/include/c++/12/bits/{*.h,*.tcc}
$ grep "Do not attempt to use it directly" /usr/include/x86_64-linux-gnu/c++/12/bits/*.h

现在,头文件 bits/stdc++.h 有点特殊,因为它用于为洞库生成预编译头。因此,它更像是一个 .cpp 实现文件,而不是一个正确的 .h 头文件 - .cpp 源代码不适用于包容性。

关于预编译头的使用,良好的 C++ 实践是使 C++ 程序/库不依赖于是否使用预编译头来构建可执行文件/库;只需遵循“包括您使用的内容”原则即可。预编译头的使用应通过外部方式(从构建系统或命令行)指定,而不是从源文件中的#include 指令指定。

从 GNU libstdc++ 的 API 的角度来看,文件 bits/stdc++.h 并未作为其一部分公开,并且仅在创建二进制 pch,并且仅给出如何从 g++命令行调用中使用此预编译头的说明,即它指示直接包含任何地方的文件在源代码中;它没有作为 libstdc++ 标头集的公共 API 的一部分公开——换句话说,它是不可包含的(本质上)。

My first thought would be that bits/stdc++.h really seems to be a internal implementation detail header of GNU libstdc++. Thus, it should never be directly included from c++ program sources.

This is based on a consistent observation that on GNU/linux, subdirectories named bits most likely seem to be the conventional place where the GNU libc and GNU libstdc++ put their internal private headers. Such headers contain implementation details, and their existence are not guaranteed to be stable across patch compiler versions.

Taking a look at the glibc headers directly located under /usr/include/x86_64-linux-gnu/bits/, almost all of them prohibit direct inclusion by use of #error directives.

Similarly, for the GNU libstdc++ headers; those are located under /usr/include/c++/12/bits/ or /usr/include/x86_64-linux-gnu/c++/12/bits/ (almost) all of them have documentation comments at the beginning such as:

/** @file bits/atomic_wait.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{atomic}
 */

Grepping under some bits subdirectories seem to indicate this directory really is reserved for the implementation. Assuming version of gcc is 12, on a x86_64 arch, try the following commands:

$ grep "Never include" /usr/include/x86_64-linux-gnu/bits/*.h
$ grep "Do not attempt to use it directly" /usr/include/c++/12/bits/{*.h,*.tcc}
$ grep "Do not attempt to use it directly" /usr/include/x86_64-linux-gnu/c++/12/bits/*.h

Now, the header bits/stdc++.h is somewhat special, as it is used to generate a precompiled header for the hole library. As such, it is more of a .cpp implementation file rather than a proper .h header file -- .cpp source are not meant for inclusion.

Regarding the use of precompiled headers, good C++ practice is to make C++ programs/libraries that do not depend on whether a precompiled header is used to build the executable/library; simply adhere to the "Include what you use" principle. Use of a precompiled header should be specified by external means, from the build system or the command line, but not from #include directives in source files.

From the viewpoint of the GNU libstdc++'s API, the file bits/stdc++.h is not exposed as being part of it, and is only mentioned in the context of creating a binary pch, and only gives instructions on how to use this precompiled header from the command line invocation of g++, namely it does not instruct to directly include the file anywhere in source code; it is not exposed as being part of the public API of libstdc++'s header set -- in other words, it is not includeable (in essence).

阳光下慵懒的猫 2025-01-22 18:25:55

正如 @Lightness Races in Orbit 提到的 Quora 问题,包含 bits/stdc++.h 没有任何问题在编程竞赛的背景下。可移植性、编译时间和标准化方面的缺点与此无关。如果示例代码使用该包含,那么在大学编程课程中也是如此。

如果您正在编写生产代码,请不要使用它。根据您当前正在编写的代码的目的来回切换应该不是什么大问题。

As explained in the top answer to the Quora question mentioned by @Lightness Races in Orbit, there's nothing wrong with including bits/stdc++.h in the context of a programming competition. The disadvantages around portability, compile time, and standardization are not relevant there. The same would be true in a college programming class if the example code uses that include.

If you're writing production code, then don't use it. It shouldn't be a big deal to switch back and forth depending on the purpose of the code you're currently writing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文