Dlaczego nie powinienem #include <bits / stdc ++. H>?

267

Wysłałem pytanie z moim kodem, którego jedyną #includedyrektywą było:

#include <bits/stdc++.h>

Mój nauczyciel kazał mi to zrobić, ale w sekcji komentarzy poinformowano mnie, że nie powinienem.

Czemu?

Lekkość Wyścigi na orbicie
źródło
72
Huh Powinienem był wiedzieć using namespace std;, że gdzieś tam będzie dostępna wersja .
user4581301,
1
dlaczego ten nagłówek w ogóle istnieje? na pewno żaden ze standardów nie obejmuje tego, skoro przyniósłby mnóstwo śmieci? a jeśli nie jest uwzględniony przez żadną publiczność, to ... dlaczego jest wysyłany do dystrybucji?
Chris Beck
10
@ChrisBeck: To szczegół implementacji. Nie jest to część „publicznego interfejsu API” ani przeznaczone do użycia. Ale wciąż musi zostać wysłane, inaczej nic by nie zadziałało. Standard obejmuje, że nie można go używać pojedynczo, ale można go używać we wstępnie skompilowanych nagłówkach. Zobacz komentarz na górze, który mówi: „To plik implementacji prekompilowanego nagłówka”. .
Wyścigi lekkości na orbicie
1
@LightnessRacesinOrbit Jeśli nie powinieneś używać go sam, w jaki sposób jego istnienie pomaga w PCH? Czy gcc jest na tyle inteligentny, że w niektórych okolicznościach automatycznie przełącza się na niego do celów PCH?
Daniel H
2
@LightnessRacesinOrbit „Nie jest częścią„ publicznego interfejsu API ”ani nie jest przeznaczona do użytku.” Zupełnie źle, jest przeznaczony do użytku publicznego, jako prekompilowany nagłówek. Libstdc ++ (pre) kompiluje i instaluje prekompilowaną wersję tego nagłówka, więc jeśli go uwzględnisz, G ++ w rzeczywistości uwzględni bits/stdc++.h.gchzamiast tego prekompilowaną wersję. Istnieje, ponieważ musi istnieć, aby można było wygenerować jego wstępnie skompilowaną wersję.
Jonathan Wakely,

Odpowiedzi:

310

Uwzględnianie <bits/stdc++.h>wydaje się coraz bardziej powszechne w stosie przepełnienia stosu, być może coś nowego w krajowym programie nauczania w bieżącym roku akademickim.

Wyobrażam sobie, że korzyści są niejasno podane w ten sposób:

  • Musisz tylko napisać jedną #includelinię
  • Nie musisz sprawdzać, w którym standardowym nagłówku jest wszystko

Niestety, jest to leniwy hack, nazywania wewnętrzny nagłówek GCC bezpośrednio zamiast poszczególnych standardowych nagłówków jak <string>, <iostream>i <vector>. Rujnuje przenośność i sprzyja okropnym nawykom.

Wady obejmują:

  • Prawdopodobnie będzie działać tylko na tym kompilatorze
  • Nie masz pojęcia, co zrobi, gdy go użyjesz, ponieważ jego zawartość nie jest ustawiana przez standard
  • Nawet samo uaktualnienie kompilatora do jego następnej wersji może uszkodzić Twój program
  • Każdy standardowy nagłówek musi zostać przeanalizowany i skompilowany wraz z kodem źródłowym, który jest powolny i powoduje, że w określonych ustawieniach kompilacji jest nieporęczny plik wykonywalny

Nie rób tego!


Więcej informacji:

Przykład, dlaczego Quora jest zły:

Lekkość Wyścigi na orbicie
źródło
77
„być może coś nowo dodanego do krajowego programu nauczania w bieżącym roku akademickim” Niewidomi na czele niewidomych :(
Przywróć Monikę
14
@KubaOber: Dokładnie.
Wyścigi lekkości na orbicie
31
Właśnie przyszedłem tutaj przez tunel czasoprzestrzenny w innym pytaniu, bardzo dobrze. Co pogarsza ten nawyk nauczania, to, że zwykle następuje po nim bezpośredni using namesapce std;. Tylko dwie linie i praktycznie każdy ładny identyfikator jest używany. Niesamowicie frustrujące, gdy się go uczy.
StoryTeller - Unslander Monica
6
Jeśli chodzi o przykład quora, mógł się zmieniać z czasem. Odwiedziłem dzisiaj stronę i zarówno zalety, jak i wady <bits / stdc ++. H> zostały wymienione w konkretnym kontekście konkursów programowania online. Uważam, że ich wnioski są w porządku.
YSC
3
@EvgeniSergeev: 2KiB to dużo kodu, danych, informacji o symbolach itp. Podczas próby ustalenia jego efektu. Czy rozumiesz wszystko, co jest dodawane? Dla twojego kompilatora? Obecna wersja? Wszystkie wydania pomiędzy? Wszystkie przyszłe wydania? Jeśli musisz zdecydować między wygodą a poprawnością, istnieje tylko jedna ważna opcja.
Widoczny
47

Czemu? Ponieważ jest używany tak, jakby miał to być standardowy nagłówek C ++, ale żaden standard go nie wspomina. Twój kod jest więc nieprzenośny z założenia. Nie znajdziesz dla niego żadnej dokumentacji na cppreference . Więc równie dobrze może nie istnieć. To wymysł czyjejś wyobraźni :)

Odkryłem - ku mojemu przerażeniu i niedowierzaniu - że istnieje dobrze znana strona z samouczkami, w której każdy przykład C ++ wydaje się zawierać ten nagłówek . Świat jest szalony. To jest dowód.


Do każdego, kto pisze takie „samouczki”

Przestań używać tego nagłówka. Zapomnij o tym. Nie propaguj tego szaleństwa. Jeśli nie chcesz zrozumieć, dlaczego to jest źle , uwierz mi na słowo. Wcale nie jestem OK traktowany jako autorytet w jakiejkolwiek sprawie i prawdopodobnie jestem tego pełen w połowie czasu, ale zrobię wyjątek tylko w tym jednym przypadku. Twierdzę, że wiem o czym tu mówię. Uwierz mi na słowo. Błagam cię

PS Mogę sobie wyobrazić obrzydliwy „standard nauczania”, w którym mógł mieć miejsce ten nikczemny pomysł, i okoliczności, które do niego doprowadziły. To, że wydawało się, że istnieje praktyczna potrzeba, nie czyni go akceptowalnym - nawet z perspektywy czasu.

PPS Nie, nie było praktycznej potrzeby. Nie ma zbyt wielu standardowych nagłówków C ++ i są one dobrze udokumentowane. Jeśli uczysz, wyrządzasz swoim uczniom krzywdę, dodając taką „magię”. Produkcja programistów o magicznym sposobie myślenia to ostatnia rzecz, jakiej chcemy. Jeśli chcesz zaoferować uczniom podzbiór języka C ++, aby ułatwić im życie, po prostu przygotuj ulotkę z krótką listą nagłówków dotyczącą kursu, którego uczysz, oraz ze zwięzłą dokumentacją dotyczącą konstrukcji bibliotek, których oczekujesz od studentów.

Przywróć Monikę
źródło
35

Istnieje witryna Stack Exchange o nazwie Programming Puzzles & Code Golf . Te puzzle programowania na tej stronie dopasować tę definicję układanki :

zabawka, problem lub inny pomysł mający na celu zabawę, stwarzając trudności do rozwiązania przez pomysłowość lub wysiłek pacjenta.

Zostały zaprojektowane z myślą o rozrywce, a nie w taki sposób, aby działający programista był rozbawiony rzeczywistym problemem napotykanym w ich codziennej pracy.

Code Golf to „rodzaj rekreacyjnych zawodów programistycznych, w których uczestnicy starają się uzyskać możliwie najkrótszy kod źródłowy, który implementuje określony algorytm”. W odpowiedziach na stronie PP&CG zobaczysz, jak ludzie określają liczbę bajtów w swoich odpowiedziach. Kiedy znajdą sposób na ogolenie kilku bajtów, wykreślą oryginalny numer i zapiszą nowy.

Jak można się spodziewać, golf-golf nagradza ekstremalne nadużycia w języku programowania. Jednoliterowe nazwy zmiennych. Brak białych znaków. Kreatywne wykorzystanie funkcji bibliotecznych. Funkcje nieudokumentowane. Niestandardowe praktyki programowania. Przerażające hacki.

Gdyby programista wysłał w pracy żądanie ściągnięcia zawierające kod w stylu golfa, zostanie ono odrzucone. Ich współpracownicy będą się z nich śmiać. Ich kierownik wpadał przy biurku na czat. Mimo to programiści bawią się, przesyłając odpowiedzi do PP&CG.

Co to ma wspólnego stdc++.h? Jak zauważyli inni, używanie go jest leniwe. Jest nieprzenośny, więc nie wiesz, czy będzie działać na twoim kompilatorze, czy na następnej wersji kompilatora. Sprzyja złym nawykom. Jest niestandardowy, więc zachowanie Twojego programu może różnić się od tego, czego oczekujesz. Może to wydłużyć czas kompilacji i rozmiar pliku wykonywalnego.

Są to wszystkie uzasadnione i poprawne zastrzeżenia. Dlaczego więc ktoś miałby używać tej potworności?

Okazuje się, że niektórzy ludzie lubią programować puzzle bez kodu golfa . Łączą się i rywalizują na imprezach takich jak ACM-ICPC, Google Code Jam i Facebook Hacker Cup, lub na stronach takich jak Topcoder i Codeforces. Ich ranga zależy od poprawności programu, szybkości wykonania i tego, jak szybko przesyłają rozwiązanie. Aby zmaksymalizować szybkość wykonywania, wielu uczestników używa C ++. Aby zmaksymalizować prędkość kodowania, niektóre z nich używają stdc++.h.

Czy to dobry pomysł? Sprawdźmy listę wad. Ruchliwość? Nie ma to znaczenia, ponieważ te zdarzenia kodowania używają określonej wersji kompilatora, którą znają wcześniej zawodnicy. Zgodność z normami? Nie dotyczy bloku kodu, którego okres użytkowania wynosi mniej niż godzinę. Skompiluj czas i rozmiar pliku wykonywalnego? Nie są one częścią rubryki punktacji konkursu.

Więc mamy złe nawyki. To jest ważny sprzeciw. Korzystając z tego pliku nagłówkowego, uczestnicy unikają szansy dowiedzenia się, który standardowy plik nagłówkowy określa funkcjonalność, z której korzystają w swoim programie. Kiedy piszą rzeczywisty kod (i nie używają stdc++.h), będą musieli spędzać czas na wyszukiwaniu tych informacji, co oznacza, że ​​będą mniej wydajni. To jest minus ćwiczenia z stdc++.h.

Rodzi to pytanie, dlaczego w ogóle warto brać udział w programowaniu konkurencyjnym, jeśli zachęca do złych nawyków, takich jak używanie stdc++.hi łamanie innych standardów kodowania. Jedną odpowiedzią jest to, że ludzie robią to z tego samego powodu, dla którego publikują programy na PP&CG: niektórzy programiści uważają za przyjemne korzystanie ze swoich umiejętności kodowania w kontekście gry.

Tak więc pytanie, czy używać, stdc++.hsprowadza się do tego, czy korzyści płynące z szybkości kodowania w konkursie programistycznym przeważają nad złymi nawykami, które można rozwinąć, używając go.

Pytanie to brzmi: „Dlaczego nie powinienem #include <bits/stdc++.h>?” Zdaję sobie sprawę, że został on poproszony o udzielenie odpowiedzi, a zaakceptowana odpowiedź ma stanowić Jedną Prawdziwą Odpowiedź na to pytanie. Ale pytanie nie brzmi „Dlaczego nie powinienem # zawierać <bits/stdc++.h>kodu produkcyjnego?” Dlatego uważam, że uzasadnione jest rozważenie innych scenariuszy, w których odpowiedź może być inna.

RedGreenCode
źródło
5
Już głosowałem, ale warto zauważyć, że „dla zabawy” to dobry powód, aby wziąć udział w programowaniu konkurencyjnym. Z drugiej strony „imponowanie potencjalnym pracodawcom” nie jest - aktywnie zaszkodzi twojej sprawie ze mną.
Martin Bonner wspiera Monikę
2
@MartinBonner Wiem, że niektórzy menedżerowie ds. Rekrutacji postrzegają konkurencyjne doświadczenie programistyczne jako czerwoną flagę. Ale dopóki najlepsze firmy programistyczne wykorzystują problemy w stylu CP podczas wywiadów i przeprowadzą konkursy programistyczne w celu znalezienia nowych rekrutów, CP będzie nadal popularny wśród początkujących programistów.
RedGreenCode
@RedGreenCode Nie jestem menedżerem (dzięki $ DEITY), ale czasami mam wpływ na rekrutację pracowników. I zdecydowanie widzę jakiekolwiek odniesienie do „programowania konkurencyjnego” jako ogromną czerwoną flagę - a nie zaletę.
Jesper Juhl,
3
@JesperJuhl Jeśli ankieterzy techniczni w Twojej firmie używają w swoich rozmowach zagadek algorytmicznych (jak wielu), daje to przewagę kandydatom z doświadczeniem w programowaniu konkurencyjnym. Być może racjonalnym wyborem dla kandydatów jest uczestnictwo w CP, ale unikaj wzmianki o tym w CV / CV.
RedGreenCode
2
Chociaż prawdą jest, że ten nagłówek może znaleźć zastosowanie w niektórych konkurencyjnych programach, nie jest całkiem skąd pochodzi. Pochodził z klasy. A ktokolwiek nauczał w tej klasie, miał wystarczający wpływ, aby zanieczyścić - poprzez kaskadę, która nastąpiła - dziesiątki, jeśli nie setki tysięcy uczniów (kształcąc nauczycieli i rówieśników, którzy następnie nieświadomie rozprzestrzeniali tę chorobę). A teraz ci uczniowie piszą również tutoriale w miejscu, w którym będą tutoriale. Chcę tylko płakać w kącie. Konkurencyjne witryny programistyczne powinny mieć wyrażenie regularne, aby odrzucić dowolny niestandardowy nagłówek .
Przywróć Monikę
8

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

17.6.1.2 Nagłówki [nagłówki]

  1. Każdy element standardowej biblioteki C ++ jest zadeklarowany lub zdefiniowany (odpowiednio) w nagłówku.

  2. Standardowa biblioteka C ++ zawiera 61 nagłówków bibliotek C ++, jak pokazano w tabeli 14.

Tabela 14 - Nagłówki bibliotek 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>

Nie ma tam <bits / stdc ++. H>. Nie jest to zaskakujące, ponieważ nagłówki <bits / ...> są szczegółami implementacji i zwykle zawierają ostrzeżenie:

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

<bits / stdc ++. h> zawiera również ostrzeżenie:

*  This is an implementation file for a precompiled header.
Magnes kulowy
źródło