Dlaczego nie powinienem #include <bits / stdc ++. H>?
Wysłałem pytanie z moim kodem, którego jedyną #include
dyrektywą była następująca:
#include <bits/stdc++.h>
Mój nauczyciel kazał mi to zrobić, ale w sekcji komentarzy poinformowano mnie, że nie powinienem.
Czemu?
Odpowiedzi
Uwzględnianie <bits/stdc++.h>
wydaje się być coraz powszechniejszą rzeczą w Stack Overflow, być może czymś nowym w krajowym programie nauczania w bieżącym roku akademickim.
Wyobrażam sobie, że korzyści są podane w ten sposób:
- Wystarczy napisać jedną
#include
linię - Nie musisz sprawdzać, w którym standardowym nagłówku wszystko się znajduje
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>
. To psuje 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 ustalona przez standard
- Nawet samo uaktualnienie kompilatora do jego własnej następnej wersji może spowodować uszkodzenie programu
- Każdy pojedynczy standardowy nagłówek musi zostać przeanalizowany i skompilowany wraz z kodem źródłowym, który jest powolny i skutkuje nieporęcznym plikiem wykonywalnym przy określonych ustawieniach kompilacji
Nie rób tego!
Więcej informacji:
- #include <bits / stdc ++. h> z programem Visual Studio nie kompiluje się
- Jak działa #include <bits / stdc ++. H> w C ++?
Przykład, dlaczego Quora jest zła:
Czemu? Ponieważ jest używany tak, jakby miał być standardowym nagłówkiem C ++, ale żaden standard o tym nie wspomina. Więc twój kod jest nieprzenośny ze względu na konstrukcję. Na cppreference nie znajdziesz żadnej dokumentacji . Więc równie dobrze mógłby nie istnieć. To wymysł czyjejś wyobraźni :)
Odkryłem - ku mojemu przerażeniu i niedowierzaniu - że istnieje dobrze znana witryna 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 robienie tego jest złe , uwierz mi na słowo. Nie jestem w porządku, gdybym był traktowany jako autorytet w czymkolwiek i prawdopodobnie jestem tym pełen w połowie przypadków, ale zrobię wyjątek tylko w tym jednym przypadku. Twierdzę, że wiem, o czym tu mówię. Wierz mi na słowo. Błagam cię.
PS Mogę sobie wyobrazić ohydny „standard nauczania”, w którym ten niegodziwy pomysł mógł mieć miejsce, i okoliczności, które do niego doprowadziły. To, że wydawało się, że istnieje praktyczna potrzeba, nie czyni tego do zaakceptowania - 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, dodając taką „magię”, wyrządzasz swoim uczniom złą przysługę. Tworzenie programistów o magicznym sposobie myślenia to ostatnia rzecz, jakiej chcemy. Jeśli chcesz zaoferować studentom podzbiór C ++, aby ułatwić im życie, po prostu przygotuj ulotkę z krótką listą nagłówków odnoszących się do kursu, którego prowadzisz, oraz zwięzłą dokumentację dotyczącą konstrukcji biblioteki, których oczekujesz od uczniów.
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 przyrząd zaprojektowany do zabawy, stwarzając trudności, które można rozwiązać dzięki pomysłowości lub cierpliwym wysiłkom.
Mają one na celu zabawę, a nie w sposób, w jaki pracujący programista mógłby być rozbawiony rzeczywistym problemem napotykanym w jego codziennej pracy.
Code Golf to „rodzaj rekreacyjnego konkursu programistycznego, w którym uczestnicy dążą do uzyskania możliwie najkrótszego kodu źródłowego, 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, aby zgolić kilka bajtów, skreślają pierwotną liczbę i zapisują nową.
Jak można się spodziewać, kodowanie w golfa nagradza ekstremalne nadużycia w języku programowania. Jednoliterowe nazwy zmiennych. Bez spacji. Kreatywne wykorzystanie funkcji biblioteki. Nieudokumentowane funkcje. Niestandardowe praktyki programistyczne. Przerażające hacki.
Jeśli programista złożyłby w pracy żądanie ściągnięcia zawierające kod w stylu golfa, zostanie ono odrzucone. Ich współpracownicy śmialiby się z nich. Ich menedżer wpadał do ich biurka na pogawędkę. 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 zadziała na twoim kompilatorze, czy w następnej wersji twojego kompilatora. Sprzyja złym nawykom. Jest niestandardowy, więc zachowanie programu może różnić się od tego, czego się spodziewasz. Może to wydłużyć czas kompilacji i rozmiar pliku wykonywalnego.
To wszystko są ważne i słuszne zastrzeżenia. Dlaczego więc ktoś miałby używać tej potworności?
Okazuje się, że niektórzy lubią programować puzzle bez kodu golfa . Spotykają się i rywalizują na imprezach takich jak ACM-ICPC, Google Code Jam i Facebook Hacker Cup lub w witrynach takich jak Topcoder i Codeforces. Ich ranking zależy od poprawności programu, szybkości wykonywania i szybkości przesyłania rozwiązania. Aby zmaksymalizować szybkość wykonywania, wielu uczestników używa C ++. Aby zmaksymalizować szybkość 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 związane z kodowaniem używają określonej wersji kompilatora, którą zawodnicy znają z góry. Zgodność z normami? Nie dotyczy bloku kodu, którego okres użytkowania jest krótszy niż jedna godzina. Czas kompilacji i rozmiar pliku wykonywalnego? Nie są one częścią tabeli punktacji konkursu.
Więc mamy złe nawyki. To jest uzasadniony sprzeciw. Używając tego pliku nagłówkowego, uczestnicy unikają szansy dowiedzenia się, który standardowy plik nagłówkowy definiuje funkcjonalność, której używają w swoim programie. Kiedy piszą kod w świecie rzeczywistym (a nie używają stdc++.h
), będą musieli spędzić czas na wyszukiwaniu tych informacji, co oznacza, że będą mniej produktywni. To wada praktyki z stdc++.h
.
Rodzi to pytanie, dlaczego w ogóle warto brać udział w programowaniu konkurencyjnym, skoro zachęca to do złych nawyków, takich jak używanie stdc++.h
i łamanie innych standardów kodowania. Jedna z odpowiedzi brzmi, że ludzie robią to z tego samego powodu, dla którego publikują programy w PP&CG: niektórzy programiści uważają, że przyjemne jest używanie ich umiejętności kodowania w kontekście podobnym do gry.
Tak więc pytanie, czy używać, stdc++.h
sprowadza się do tego, czy korzyści z szybkości kodowania w konkursie programistycznym przeważają nad złymi nawykami, które można rozwinąć, stosując go.
To pytanie brzmi: „Dlaczego nie powinienem #include <bits/stdc++.h>
?” Zdaję sobie sprawę, że zadano to pytanie i udzielono mu odpowiedzi, a przyjęta odpowiedź ma być jedyną prawdziwą odpowiedzią na to pytanie. Ale pytanie nie brzmi „Dlaczego nie powinienem # uwzględniać <bits/stdc++.h>
w kodzie produkcyjnym?” Dlatego uważam, że rozsądne jest rozważenie innych scenariuszy, w których odpowiedź może być inna.
Od N4606, Wersja robocza, Standard języka programowania C ++:
17.6.1.2 Nagłówki [headers]
Każdy element biblioteki standardowej C ++ jest zadeklarowany lub zdefiniowany (odpowiednio) w nagłówku.
Biblioteka standardowa C ++ zawiera 61 nagłówków biblioteki C ++, jak pokazano w tabeli 14.
Tabela 14 - Nagłówki biblioteki 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>
Tam nie ma <bits / stdc ++. H>. Nie jest to zaskakujące, ponieważ nagłówki <bits / ...> zawierają szczegóły 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.
Powód, dla którego nie używamy:
#include <bits/stdc++.h>
wynika z wydajności. Pozwólcie, że zrobię analogię: dla tych z Was, którzy znają Javę: gdybyście zapytali swojego instruktora, czy poniższe rozwiązanie jest dobrym pomysłem, chyba że jest złym instruktorem, powiedzieliby nie:
import java.*.*
Funkcja #include ... zasadniczo robi to samo ... To nie jedyny powód, aby go nie używać, ale jest to jeden z głównych powodów, aby go nie używać. Dla porównania z prawdziwego życia: wyobraź sobie, że masz bibliotekę i chciałbyś pożyczyć kilka książek z biblioteki, czy przeniósłbyś całą bibliotekę obok domu? Byłoby drogie i nieefektywne. Jeśli potrzebujesz tylko 5 książek, to wyjmij tylko 5 ... Nie całą bibliotekę .....
#include <bits/stdc++.h>
Wygląda dobrze na wygląd programu. Wystarczy wpisać jedną instrukcję włączania i działa, tak samo jest z przenoszeniem całej biblioteki, spójrz, wystarczy przenieść całą bibliotekę zamiast 5 książek po kolei. Wydaje ci się to wygodne, to znaczy dla osoby, która faktycznie musi przeprowadzić przeprowadzkę? Nie tak bardzo i zgadnij, co w C ++ osoba wykonująca przenoszenie będzie Twoim komputerem ... Komputer nie będzie zadowolony z przenoszenia całej biblioteki dla każdego pliku źródłowego, który napiszesz:) .....