为什么不#include <bits / stdc ++。h>?


267

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

#include <bits/stdc++.h>

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

为什么?


72
嗯 我应该知道using namespace std;某个地方会有一个包含版本。
user4581301 2015年

1
为什么这个标头甚至存在?当然,没有一个标准实际上包括这个标准,因为它会带来很多垃圾?如果它不被任何公众包括在内...那么为什么将它运送到发行版中?
克里斯·贝克

10
@ChrisBeck:这是一个实现细节。它不是“公共API”的一部分,也不是供使用的。但是它仍然必须被运送,否则将无法正常工作。该标准可能不会单独使用,但可以在预编译的标头中使用。请参阅顶部的注释,其中说:“这是预编译标头的实现文件。”
Lightness Races in Orbit

1
@LightnessRacesinOrbit如果您不应该自己使用它,那么它的存在对PCH有何帮助?还是gcc足够智能,在某些情况下可以自动切换到PCH?
Daniel H

2
@LightnessRacesinOrbit “它不是“公共API”的一部分,也不是要使用的。” 完全错误,它应作为预编译的头文件供公共使用。Libstdc ++(预编译)会编译并安装该标头的预编译版本,因此,如果包含该标头,则G ++实际上会包含bits/stdc++.h.gch该预编译版本。之所以存在,是因为它必须存在,以便可以生成其预编译版本。
乔纳森·威克利

Answers:


310

<bits/stdc++.h>在Stack Overflow上似乎越来越常见,包括在当前学年的国家课程中新增的内容。

我想这样就隐约地给出了优势:

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

不幸的是,这是一个懒惰劈,命名GCC内部报头,而不是直接从个人标准头像<string><iostream><vector>。它破坏了便携性并养成了可怕的习惯。

缺点包括:

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

别做!


更多信息:

Quora为何不好的示例:


77
“也许是本学年在国家课程中新增的内容”盲人领导盲人:(
恢复莫妮卡2015年

14
@KubaOber:是的。

31
只是通过虫洞来到这里,这是另一个问题,很好。使这种教学习惯更糟的是,它通常是直接的using namesapce std;。仅使用两行,实际上使用了每个不错的标识符。令人沮丧的是看到它被教导了。
StoryTeller-Unslander Monica

6
关于法定人数示例,它可能会随着时间而变化。我今天已经访问了该页面,并且在在线编程竞赛的特定上下文中列出了<bits / stdc ++。h>的优缺点。我认为他们的结论可以。
YSC

3
@EvgeniSergeev:2KiB是很多代码,数据,符号信息等,试图确定其效果时。您了解所添加的所有内容吗?对于您的编译器?当前版本?所有版本之间?所有将来的版本?如果您需要在方便性和正确性之间做出选择,则只有一个有效选项。
IInspectable '18年

47

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

令我震惊和怀疑的是,我发现有一个著名的教程站点,每个C ++示例似乎都包含此标头。世界疯了。这就是证明。


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

请停止使用此标题。忘掉它。不要传播这种疯狂。如果您不愿意理解为什么这样做是错误的,请相信我。我根本不被视为任何事物上的权威人物,而且我可能有一半时间都饱受权威的束缚,但仅在这种情况下,我会做一个例外。我声称我知道我在说什么。相信我。我恳求你。

PS:我完全可以想象这个邪恶的想法可能发生的可恶的“教学标准”,以及导致它的情况。仅因为似乎实际需要它并不能使它接受-甚至没有回想起来。

PPS不,没有实际需要。没有太多的C ++标准头文件,而且它们都有据可查。如果您教书,那么添加“魔术”对您的学生是有害的。培养具有神奇思维方式的程序员是我们想要的最后一件事。如果您需要为学生提供C ++的子集以使他们的生活更轻松,只需提供一份讲义,上面附有适用于您所教课程的标题的简短列表,并提供希望学生使用的库结构的简洁文档。


35

有一个称为Programming Puzzles&Code Golf的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 <bits/stdc++.h>?” 我意识到有人提出并回答了这个问题,所接受的答案旨在成为该问题的唯一真实答案。但是问题不是“为什么不应该<bits/stdc++.h>在生产代码中包含#?” 因此,我认为考虑答案可能不同的其他情况是合理的。


5
我已经投票赞成,但是可能值得指出的是,“为了好玩”是参加竞争性编程的一个很好的理由。另一方面,“打动潜在雇主”不是-它会积极损害您对我的要求。
马丁·邦纳

2
@MartinBonner我知道一些招聘经理将竞争性编程经验视为危险信号。但是,只要顶级软件公司在面试中使用CP风格的问题并举办编程竞赛来寻找新人,CP就会继续在有抱负的开发人员中流行。
RedGreenCode

@RedGreenCode我不是经理(感谢$ DEITY),但有时对聘请部门有影响。而且,我绝对会将对“竞争性编程”的任何提及视为巨大的危险信号- 并非优势。
Jesper Juhl

3
@JesperJuhl如果您公司的技术面试官在面试中使用算法难题(与许多人一样),那么具有竞争性编程经验的应聘者将具有优势。候选人的合理选择也许是参加CP,但要避免在简历/简历中提及。
RedGreenCode

2
虽然确实可以在一些竞争性编程中找到此标头,但它的来源并不完全。它来自教室。而且,在那个教室里任教的人都有足够的影响力-通过随后的级联-污染了成千上万甚至数十万学生(通过对当时无意中已经在传播这种疾病的老师和同伴进行教育)。现在,这些学生还在用教程编写教程。我只想在一个角落里哭泣。竞争性编程站点应该只使用正则表达式来拒绝任何非标准标头
恢复莫妮卡

8

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

17.6.1.2标头[headers]

  1. 在标头中声明或定义了C ++标准库的每个元素。

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

表14 — C ++库头

<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>

那里没有<bits / stdc ++。h>。这并不奇怪,因为<bits / ...>头是实现细节,通常带有警告:

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

<bits / stdc ++。h>也带有警告:

*  This is an implementation file for a precompiled header.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.