Powiedziano mi przez innych, że pisanie using namespace std;
w kodzie jest źle, i że powinno się używać std::cout
i std::cin
bezpośrednio zamiast.
Dlaczego using namespace std;
uważa się za złą praktykę? Czy jest nieefektywny, czy ryzykuje zadeklarowanie niejednoznacznych zmiennych (zmiennych o tej samej nazwie co funkcja w std
przestrzeni nazw)? Czy wpływa to na wydajność?
c++
namespaces
std
using-directives
c++-faq
akbiggs
źródło
źródło
std::literals::chrono_literals
,Poco::Data:Keywords
,Poco::Units
a rzeczy, które będą zajmować się literałów lub sztuczek czytelność. Ilekroć znajduje się w plikach nagłówka lub implementacji. Wydaje mi się, że może być OK w zakresie funkcji, ale oprócz literałów i innych rzeczy nie jest to przydatne.Odpowiedzi:
W ogóle nie ma to związku z wydajnością. Ale zastanów się: używasz dwóch bibliotek o nazwach Foo i Bar:
Wszystko działa dobrze i bez problemu możesz dzwonić
Blah()
z Foo iQuux()
Bar. Ale pewnego dnia zaktualizujesz do nowej wersji Foo 2.0, która teraz oferuje funkcję o nazwieQuux()
. Teraz masz konflikt: Zarówno Foo 2.0, jak i Bar importują sięQuux()
do Twojej globalnej przestrzeni nazw. Będzie to wymagać pewnego wysiłku, aby naprawić, szczególnie jeśli parametry funkcji się zgadzają.Gdybyś użył
foo::Blah()
ibar::Quux()
, to wprowadzeniefoo::Quux()
byłoby nie-wydarzeniem.źródło
#define
polega na tym, że nie ogranicza się do przestrzeni nazw, ale depcze po całej bazie kodu. Alias przestrzeni nazw jest tym, czego chcesz.Zgadzam się ze wszystkim, co napisał Greg , ale chciałbym dodać: Może być nawet gorzej niż powiedział Greg!
Biblioteka Foo 2.0 mogłaby wprowadzić funkcję,
Quux()
która jest jednoznacznie lepsza dla niektórych twoich wywołańQuux()
niżbar::Quux()
kod wywoływany przez lata. Wtedy twój kod wciąż się kompiluje , ale po cichu wywołuje niewłaściwą funkcję i robi Bóg-wie-co. To jest tak złe, jak tylko się da.Należy pamiętać, że
std
przestrzeń nazw ma mnóstwo identyfikatorów, z których wiele jest bardzo spotykane (myślęlist
,sort
,string
,iterator
, itd.), Które są bardzo prawdopodobne, aby pojawić się w innym kodem, too.Jeśli uważasz, że jest to mało prawdopodobne: na przepełnieniu stosu pojawiło się pytanie , w którym dokładnie to się stało (zła funkcja została wywołana z powodu pominiętego
std::
prefiksu) około pół roku po udzieleniu tej odpowiedzi. Oto kolejny, bardziej aktualny przykład takiego pytania. To jest prawdziwy problem.Oto jeszcze jeden punkt danych: wiele, wiele lat temu uważałem, że denerwujące jest to, że muszę poprzedzać wszystko standardową biblioteką
std::
. Potem pracowałem nad projektem, w którym na początku zdecydowano, że zarównousing
dyrektywy, jak i deklaracje są zakazane, z wyjątkiem zakresów funkcji. Zgadnij co? Większość z nas zajęło kilka tygodni przyzwyczajenie się do pisania prefiksu, a po kilku kolejnych tygodniach większość z nas nawet zgodziła się, że w rzeczywistości kod jest bardziej czytelny . Jest po temu powód: to, czy lubisz krótszą czy dłuższą prozę, jest subiektywne, ale przedrostki obiektywnie zwiększają przejrzystość kodu. Nie tylko kompilator, ale i Ty łatwiej jest sprawdzić, do którego identyfikatora się odnosi.W ciągu dekady ten projekt urósł do kilku milionów wierszy kodu. Ponieważ dyskusje te pojawiają się wielokrotnie, raz byłem ciekawy, jak często (dozwolony) zakres funkcji
using
faktycznie był używany w projekcie. Przeszukałem źródła i znalazłem tylko jeden lub dwa tuziny miejsc, w których był używany. Dla mnie oznacza to, że po wypróbowaniu programiści nie są nastd::
tyle bolesni, by stosować dyrektywy nawet raz na każde 100 kLoC, nawet jeśli pozwolono na ich użycie.Konkluzja: Jawne prefiksowanie wszystkiego nie wyrządza żadnej szkody, przyzwyczaja się bardzo mało i ma obiektywne zalety. W szczególności ułatwia interpretację kodu przez kompilator i czytelników - i to prawdopodobnie powinno być głównym celem podczas pisania kodu.
źródło
string
klasę i najwyraźniej każda biblioteka miała swoją własną. Powiem ci, co: będziemy dalej pisać nasz kodstd::
i możesz go przepuszczaćgrep -v std:: | vim
podczas przeglądania. Możesz też nauczyć swojego edytora, żestd::
jest słowem kluczowym, które ma być tak samo kolorowe, jak kolor tła. Cokolwiek działa.std::
był szkodliwy. Zawiera bardzo ważne informacje (a mianowicie „to, co nastąpi później, jest częścią standardowej biblioteki”, i wciąż jest dość krótkim i zwartym prefiksem. Przez większość czasu nie stanowi to żadnego problemu. Czasami masz kilka linii kodu gdzie trzebastd
często odwoływać się do określonych symboli w przestrzeni nazw, a następnieusing
stwierdzenie w tym konkretnym zakresie ładnie rozwiązuje problem. Ale w ogólnym przypadku nie jest to hałas, przekazuje cenne informacje oprócz usuwania dwuznaczności.std::
, wiem, że to będziestd::
bez zastanowienia. Jeśli widzęstring
lublist
lubmap
przez siebie, zastanawiam się trochę.vector
,transform
albodistance
. A to tylko przykłady wielu bardzo popularnych nazw używanych w standardowej bibliotece. Sugerowanie, aby nie używać ich ze strachu lub stronnicze opinie na temat funkcji przestrzeni nazw, która jest integralną częścią C ++, przynosi efekt przeciwny do zamierzonego.Problem z umieszczaniem
using namespace
w plikach nagłówkowych twoich klas polega na tym, że zmusza każdego, kto chce użyć twoich klas (włączając pliki nagłówkowe), by również „używały” (tj. Widziały wszystko w) tych innych przestrzeniach nazw.Możesz jednak umieścić instrukcję using w swoich (prywatnych) plikach * .cpp.
Strzeż się, że niektórzy nie zgadzają się z moim powiedzeniem „czuj się swobodnie” w ten sposób - ponieważ chociaż
using
oświadczenie w pliku cpp jest lepsze niż w nagłówku (ponieważ nie dotyczy to osób, które zawierają plik nagłówka), myślą, że nadal nie jest dobry (ponieważ w zależności od kodu może to utrudnić utrzymanie implementacji klasy). Ten wpis C ++ Super-FAQ mówi:FAQ sugeruje dwie alternatywy:
Deklaracja użycia:
Po prostu wpisuję std ::
źródło
Niedawno spotkałem się ze skargą dotyczącą programu Visual Studio 2010 . Okazało się, że prawie wszystkie pliki źródłowe miały te dwie linie:
Wiele funkcji Boost przechodzi do standardu C ++ 0x, a Visual Studio 2010 ma wiele funkcji C ++ 0x, więc nagle te programy się nie kompilowały.
Dlatego unikanie
using namespace X;
jest formą zabezpieczenia na przyszłość, sposobem upewnienia się, że zmiana używanych bibliotek i / lub plików nagłówkowych nie spowoduje uszkodzenia programu.źródło
using
poza definicją funkcji i rzadko używamusing namespace
w ogóle.Wersja skrócona: nie używaj globalnych
using
deklaracji ani dyrektyw w plikach nagłówków. Używaj ich w plikach implementacyjnych. Oto, co Herb Sutter i Andrei Alexandrescu mają do powiedzenia na ten temat w standardach kodowania C ++ (pogrubienie dla podkreślenia jest moje):źródło
using
nigdy nie powinno pojawiać się w nagłówku, nie jestem tak przekonany o bezpłatnej licencji na umieszczenieusing namespace xyz;
dowolnego miejsca w kodzie, szczególnie jeślixyz
jeststd
. Korzystam z tegousing std::vector;
formularza, ponieważ wyciąga on tylko jeden element z przestrzeni nazw do zakresu pseudoglobalnego, co prowadzi do znacznie mniejszego ryzyka kolizji.using namespace
to złogoto
jest jak zło. Oba mają prawidłowe zastosowania, ale 999 razy na 1000 będą niewłaściwie użyte. Tak, tak,using namespace
w źródle nie będzie zanieczyszczać przestrzeni nazw innych włączników. Ale nadal nie ochroni cię przed „zabawą”, która powstaje zusing namespace Foo
+using namespace Bar
, gdy dzwonisz (domyślnie Foo: :)baz(xyz)
i nagle łamie się kod (bez powiązanych zmian) tylko dlatego, że ponieważBar::baz()
został gdzieś dodany, co akurat jest lepsze match (i dlatego teraz zostaje wywołany)Nie należy stosować
using
dyrektywy w zakresie globalnym, szczególnie w nagłówkach. Są jednak sytuacje, w których jest to właściwe nawet w pliku nagłówkowym:Jest to lepsze niż kwalifikacja jawna (
std::sin
,std::cos
...), ponieważ jest krótsze i ma możliwość pracy z typami zmiennoprzecinkowymi zdefiniowanymi przez użytkownika (za pomocą wyszukiwania zależnego od argumentów (ADL)).źródło
using std::cos;
,using std::sin
itd. Problem polega jednak na tym, że każdy dobrze zaprojektowanyuserlib
będzie miał swoją własną przestrzeń nazwsin
icos
wewnątrz niej, więc to naprawdę nie pomaga. (Chyba, żeusing namespace userlib
przed tym szablonem jest tak samo źleusing namespace std
- a jego zakres nie jest ograniczony.) Ponadto jedyną taką funkcją, jaką kiedykolwiek widziałem, jestswap
, i w takich przypadkach zaleciłbym utworzenie szablonu specjalizacjastd::swap
i unikanie całego problemu.template<typename T> void swap(MyContainer<T>&, MyContainer<T>&)
(Nie ma częściowej specjalizacji szablonu funkcji (FTPS), więc czasami trzeba zamiast tego uciekać się do przeciążania)x
ma co najmniej jedną „powiązaną przestrzeń nazw” (np. Jeśli została zdefiniowana wnamespace userlib
), wówczas każde wywołanie funkcji, które wygląda tak,cos(x)
będzie dodatkowo wyglądać w tych przestrzeniach nazw - bez koniecznościusing namespace userlib;
wcześniejszego. Zan Lynx ma rację (a wyszukiwanie nazw C ++ jest bizantyjskie ...)Nie używaj go globalnie
Jest uważany za „zły” tylko wtedy, gdy jest używany globalnie . Ponieważ:
using namespace xyz
.using namespace std
możesz nie być świadomy wszystkich rzeczy, które chwytasz - a gdy dodasz kolejną#include
lub przejdziesz do nowej wersji C ++, możesz mieć konflikty nazw, o których nie wiedziałeś.Możesz używać go lokalnie
Śmiało i używaj go lokalnie (prawie) swobodnie. To oczywiście zapobiega powtarzaniu się
std::
- a powtarzanie jest również złe.Idiom używający go lokalnie
W C ++ 03 istniał idiom - kociołkowy kod - do implementacji
swap
funkcji dla twoich klas. Zasugerowano, że faktycznie używasz lokalnegousing namespace std
- a przynajmniejusing std::swap
:To robi następującą magię:
std::swap
forvalue_
, tjvoid std::swap(int, int)
.void swap(Child&, Child&)
zaimplementowane przeciążenie, kompilator go wybierze.void std::swap(Child&,Child&)
i spróbuje jak najlepiej zamienić je.W C ++ 11 nie ma powodu, aby używać tego wzorca. Implementacja
std::swap
została zmieniona, aby znaleźć potencjalne przeciążenie i wybrać to.źródło
swap
nie jest już tak ważne w C ++ 11, ponieważstd::swap
sam w sobie jest bardziej elastyczny (używa semantyki ruchu). Alestd::swap
automatycznie wybieram własną niestandardową wymianę, co jest dla mnie absolutnie nowe (i tak naprawdę w to nie wierzę).using std::swap;
a nieusing namespace std;
. Bardziej szczegółowy idiom ma mniej skutków ubocznych i dlatego sprawia, że kod jest łatwiejszy w utrzymaniu.swap
, a różne inne miejsca w standardzie zostały zmienione, aby powiedzieć, żeswap
tak nazywają (NB, jak wspomniano powyżej,using std::swap
jest właściwą drogą, a nieusing namespace std
). Alestd::swap
samo to nie zostało zdecydowanie zmienione, aby znaleźć inneswap
i użyć go. Jeślistd::swap
zostanie wywołany, wtedystd::swap
się przyzwyczai.using std::swap
lokalne, aby zmniejszyć lokalną przestrzeń nazw, jednocześnie tworząc kod samokontrujący. Rzadko kiedy interesuje Cię cała przestrzeń nazw, więc po prostu wybierz części, którymi jesteś zainteresowany.Jeśli importujesz odpowiednie pliki nagłówkowe nagle mają nazwy jak
hex
,left
,plus
lubcount
w swoim zasięgu globalnym. Może to być zaskakujące, jeśli nie wiesz, żestd::
zawierają te nazwy. Jeśli spróbujesz także użyć tych nazw lokalnie, może to prowadzić do pewnych nieporozumień.Jeśli wszystkie standardowe elementy znajdują się we własnej przestrzeni nazw, nie musisz się martwić o kolizje nazw z kodem lub innymi bibliotekami.
źródło
distance
. nadal wolę nazwy niekwalifikowane, o ile jest to praktycznie możliwe, ponieważ zwiększa to dla mnie czytelność. plus, myślę, że fakt, iż zwykle nie kwalifikujemy się do mówienia i jesteśmy gotowi poświęcić czas na rozwiązywanie ewentualnych niejasności, oznacza, że warto zrozumieć, o czym mówi się bez kwalifikacji, i zastosować do źródła kod, który oznacza, że jest skonstruowany w taki sposób, że jest jasne, o co w tym wszystkim chodzi, nawet bez kwalifikacji.<iomanip>
. Nadal dobry punkt.Kolejnym powodem jest niespodzianka.
Jeśli widzę
cout << blah
, zamiaststd::cout << blah
myśleć: co to jestcout
? Czy to normalnecout
? Czy to jest coś specjalnego?źródło
cout
jest złym przykładem, ponieważ wszyscy go rozpoznają. Ale wyobraź sobiefuture
w aplikacji finansowej. Czy jest to umowa kupna lub sprzedaży czegoś w określonym terminie? Nie, nie jest. Jeśli kod mówistd::future
, że nie byłbyś tak łatwo zmieszany.Doświadczeni programiści używają wszystkiego, co rozwiązuje ich problemy i unikają tego, co stwarza nowe problemy, i unikają dyrektyw używania na poziomie plików nagłówkowych z tego właśnie powodu.
Doświadczeni programiści starają się również unikać pełnej kwalifikacji nazw w swoich plikach źródłowych. Niewielkim powodem jest to, że pisanie większej ilości kodu, gdy mniej kodu jest wystarczające, nie jest eleganckie, chyba że istnieją uzasadnione powody . Głównym tego powodem jest wyłączenie wyszukiwania zależnego od argumentów (ADL).
Jakie są te dobre powody ? Czasami programiści wyraźnie chcą wyłączyć ADL, innym razem chcą ujednoznacznić.
Więc następujące są w porządku:
źródło
Zgadzam się, że nie powinien być używany globalnie, ale nie jest tak źle używać lokalnie, jak w
namespace
. Oto przykład z „The C ++ Programming Language” :W tym przykładzie rozwiązaliśmy potencjalne konflikty nazw i niejednoznaczności wynikające z ich składu.
Nazwy wyraźnie tam zadeklarowane (w tym nazwy zadeklarowane przy użyciu deklaracji użycia, takich jak
His_lib::String
) mają pierwszeństwo przed nazwami udostępnionymi w innym zakresie za pomocą dyrektywy using (using namespace Her_lib
).źródło
Uważam to również za złą praktykę. Dlaczego? Pewnego dnia pomyślałem, że funkcją przestrzeni nazw jest dzielenie rzeczy, więc nie powinienem zepsuć tego wrzucaniem wszystkiego do jednej globalnej torby.
Jeśli jednak często używam „cout” i „cin”, piszę:
using std::cout; using std::cin;
w pliku .cpp (nigdy w pliku nagłówkowym, jak się propaguje#include
). Myślę, że nikt rozsądny nigdy nie nazwie strumieniacout
anicin
. ;)źródło
Miło jest widzieć kod i wiedzieć, co robi. Jeśli widzę
std::cout
, wiem, że tocout
strumieństd
biblioteki. Jeśli widzęcout
, to nie wiem. Może to byćcout
strumieństd
biblioteki. Lub może byćint cout = 0;
dziesięć linii wyżej w tej samej funkcji. Lubstatic
zmienna nazwanacout
w tym pliku. To może być cokolwiek.Teraz weź milion kodów wiersza, który nie jest szczególnie duży, i szukasz błędu, co oznacza, że wiesz, że jeden milion wierszy nie wykonuje tego, co powinien.
cout << 1;
mógł odczytaćstatic int
nazwanycout
, przesunąć go w lewo o jeden bit i wyrzucić wynik. Szukając błędu, musiałbym to sprawdzić. Czy widzisz, jak naprawdę wolę widziećstd::cout
?Jest to jedna z tych rzeczy, które wydają się być naprawdę dobrym pomysłem, jeśli jesteś nauczycielem i nigdy nie musiałeś pisać i utrzymywać żadnego kodu do życia. Uwielbiam widzieć kod, w którym (1) wiem, co on robi; oraz (2) Jestem przekonany, że osoba, która to pisze, wiedziała, co robi.
źródło
Chodzi o zarządzanie złożonością. Korzystanie z przestrzeni nazw spowoduje wciągnięcie rzeczy, których nie chcesz, a tym samym może utrudnić debugowanie (mówię prawdopodobnie). Używanie std :: w dowolnym miejscu jest trudniejsze do odczytania (więcej tekstu i tak dalej).
Konie na kursy - zarządzaj swoją złożonością, jak najlepiej potrafisz i czujesz się w stanie.
źródło
Rozważać
Pamiętaj, że jest to prosty przykład. Jeśli masz pliki z 20 dołączeniami i innymi importami, będziesz mieć mnóstwo zależności, aby przejść do rozwiązania problemu. Najgorsze jest to, że w innych modułach można uzyskać niepowiązane błędy w zależności od sprzecznych definicji.
Nie jest to okropne, ale zaoszczędzisz sobie bólu głowy, nieużywając go w plikach nagłówków lub globalnej przestrzeni nazw. Prawdopodobnie dobrze jest to robić w bardzo ograniczonych zakresach, ale nigdy nie miałem problemu z wpisaniem dodatkowych pięciu znaków, aby wyjaśnić, skąd biorą się moje funkcje.
źródło
Musisz umieć czytać kod napisany przez ludzi, którzy mają inny styl i opinie na temat najlepszych praktyk niż Ty.
Jeśli tylko używasz
cout
, nikt się nie myli. Ale kiedy masz dużo przestrzeni nazw latających i widzisz tę klasę i nie jesteś do końca pewien, co ona robi, wyraźne określenie przestrzeni nazw działa jak komentarz. Na pierwszy rzut oka widać „och, to jest operacja systemu plików” lub „robi to w sieci”.źródło
Używanie wielu przestrzeni nazw jednocześnie jest oczywiście receptą na katastrofę, ale używanie przestrzeni nazw JUST
std
i tylko przestrzeni nazwstd
nie jest moim zdaniem wielkim problemem, ponieważ redefinicja może nastąpić tylko na podstawie własnego kodu ...Więc po prostu rozważ ich funkcje jako zastrzeżone nazwy, takie jak „int” lub „class” i to wszystko.
Ludzie powinni przestać być tak anonimowi. Twój nauczyciel miał rację przez cały czas. Wystarczy użyć JEDNEJ przestrzeni nazw; taki jest sens używania przestrzeni nazw na pierwszym miejscu. Nie należy używać więcej niż jednego jednocześnie. Chyba że to twoje. Ponownie, redefinicja nie nastąpi.
źródło
min
,end
iless
pojawiają się wstd::
przestrzeni nazw. Co więcej, teraz, gdystd::
ma w sobie tysiące symboli, przydatne jest, aby czytelnik wiedział, skąd pochodzi nowy symbol, którego mogą nie znać.Zgadzam się z innymi tutaj, ale chciałbym zająć się obawami dotyczącymi czytelności - możesz tego wszystkiego uniknąć, po prostu używając typedefs na górze pliku, funkcji lub deklaracji klasy.
Zwykle używam go w mojej deklaracji klasy, ponieważ metody w klasie mają tendencję do radzenia sobie z podobnymi typami danych (członkami), a typedef to możliwość przypisania nazwy, która ma znaczenie w kontekście klasy. To faktycznie poprawia czytelność w definicjach metod klasowych.
oraz we wdrażaniu:
w przeciwieństwie do:
lub:
źródło
Konkretny przykład wyjaśniający problem. Wyobraź sobie, że masz sytuację, w której masz dwie biblioteki
foo
ibar
każda z własną przestrzenią nazw:Załóżmy teraz, że używasz
foo
ibar
razem w swoim własnym programie w następujący sposób:W tym momencie wszystko jest w porządku. Po uruchomieniu programu „robi coś”. Ale później zaktualizujesz
bar
i powiedzmy, że zmieniło się to tak:W tym momencie pojawi się błąd kompilatora:
Musisz więc wykonać pewne czynności konserwacyjne, aby wyjaśnić, że „a” oznacza
foo::a
. To niepożądane, ale na szczęście jest dość łatwe (wystarczy dodaćfoo::
przed wszystkimi połączeniami za
że kompilator oznaczy jako niejednoznaczny).Ale wyobraź sobie alternatywny scenariusz, w którym zamiast tego pasek zmienia się i wygląda tak:
W tym momencie twoje wezwanie do
a(42)
nagle wiąże siębar::a
zamiastfoo::a
i zamiast robić „coś” robi „coś zupełnie innego”. Żadnych ostrzeżeń kompilatora ani nic takiego. Twój program po prostu po cichu zaczyna robić coś zupełnie innego niż wcześniej.Korzystając z przestrzeni nazw, ryzykujesz taki scenariusz, dlatego ludzie nie czują się komfortowo, używając przestrzeni nazw. Im więcej rzeczy w przestrzeni nazw, tym większe ryzyko konfliktu, więc ludzie mogą być jeszcze bardziej niekomfortowi podczas korzystania z przestrzeni nazw
std
(z powodu liczby rzeczy w tej przestrzeni nazw) niż w innych przestrzeniach nazw.Ostatecznie jest to kompromis między zapisywalnością a niezawodnością / konserwowalnością. Czytelność może również uwzględniać, ale widziałem argumenty przemawiające w obu kierunkach. Zwykle powiedziałbym, że niezawodność i łatwość konserwacji są ważniejsze, ale w tym przypadku będziesz stale płacić koszty zapisu za dość rzadki wpływ na niezawodność / łatwość konserwacji. „Najlepszy” kompromis określi twój projekt i twoje priorytety.
źródło
Przestrzeń nazw to nazwany zakres. Przestrzenie nazw służą do grupowania powiązanych deklaracji i oddzielania oddzielnych elementów. Na przykład dwie osobno opracowane biblioteki mogą używać tej samej nazwy w odniesieniu do różnych elementów, ale użytkownik może nadal używać obu:
Powtarzanie nazwy przestrzeni nazw może rozpraszać uwagę zarówno czytelników, jak i pisarzy. W związku z tym można stwierdzić, że nazwy z określonej przestrzeni nazw są dostępne bez wyraźnej kwalifikacji. Na przykład:
Przestrzenie nazw stanowią potężne narzędzie do zarządzania różnymi bibliotekami i różnymi wersjami kodu. W szczególności oferują one programistom alternatywne sposoby wyraźnego odwołania się do nielokalnej nazwy.
Źródło: Przegląd języka programowania C ++ autorstwa Bjarne Stroustrup
źródło
Przykład, w którym
using namespace std
zgłaszany jest błąd kompilacji z powodu niejednoznaczności zliczania, która jest również funkcją biblioteki algorytmów.źródło
::count
--problem rozwiązany. Zwykle będziesz mieć więcej rzeczy ze standardowej przestrzeni nazw niż z innych miejsc, więc utrzymywanie dyrektywy używającej przestrzeni nazw może zaoszczędzić ci pisania.Nie pogarsza to wydajności oprogramowania ani projektu. Włączenie przestrzeni nazw na początku kodu źródłowego nie jest złe. Uwzględnienie
using namespace std
instrukcji różni się w zależności od potrzeb i sposobu opracowywania oprogramowania lub projektu.namespace std
Zawiera C ++ standardowe funkcje i zmienne. Ta przestrzeń nazw jest przydatna, gdy często używasz standardowych funkcji C ++.Niektórzy mówili, że włączanie
using namespace std
plików źródłowych do plików źródłowych jest złą praktyką, ponieważ wywołujesz z tej przestrzeni nazw wszystkie funkcje i zmienne. Gdy chcesz zdefiniować nową funkcję o tej samej nazwie co inna funkcja w niej zawartanamespace std
, przeciążasz tę funkcję i może to powodować problemy z powodu kompilacji lub wykonania. Nie będzie się kompilować ani wykonywać zgodnie z oczekiwaniami.źródło
Nie sądzę, aby była to zła praktyka we wszystkich warunkach, ale musisz zachować ostrożność, gdy z niej korzystasz. Jeśli piszesz bibliotekę, prawdopodobnie powinieneś użyć operatorów rozdzielczości zakresu z przestrzenią nazw, aby powstrzymać swoją bibliotekę przed wpadaniem na inne biblioteki. W przypadku kodu poziomu aplikacji nie widzę w nim nic złego.
źródło
„Dlaczego„ używa przestrzeni nazw std; ” uważałeś za złą praktykę w C ++? ”
Mówię inaczej: dlaczego wpisywanie pięciu dodatkowych znaków jest przez niektórych uważane za nieporęczne?
Rozważ np. Napisanie oprogramowania numerycznego. Dlaczego miałbym nawet brać pod uwagę zanieczyszczenie mojej globalnej przestrzeni nazw przez zmniejszenie ogólnego „std :: vector” do „vector”, gdy „vector” jest jedną z najważniejszych koncepcji domeny problemowej?
źródło
cout << hex << setw(4) << i << endl;
jest łatwiejszy do odczytania niżstd::cout << std::hex << std::setw(4) << i << std::endl;
std::map<std::string,std::pair<std::string,std::string>>
jest okropny w porównaniu domap<string,pair<string,string>>
.Zgadzam się z innymi - żąda konfliktów nazw, dwuznaczności, a faktem jest, że jest mniej wyraźny. Chociaż widzę użycie
using
, moim osobistym wyborem jest ograniczenie go. Chciałbym również mocno rozważyć to, co zauważyli inni:Jeśli chcesz znaleźć nazwę funkcji, która może być dość popularną nazwą, ale chcesz ją znaleźć tylko w
std
przestrzeni nazw (lub odwrotnie - chcesz zmienić wszystkie wywołania, które nie znajdują się w przestrzeni nazwstd
, przestrzeni nazwX
, ...), to jak proponujesz to zrobić?Możesz napisać program, aby to zrobić, ale czy nie lepiej byłoby poświęcić czas na pracę nad samym projektem, niż na pisanie programu do obsługi projektu?
Osobiście nie mam nic przeciwko temu
std::
prefiksowi. Lubię ten wygląd bardziej niż brak go. Nie wiem, czy to dlatego, że jest jawne i mówi mi „to nie jest mój kod ... używam standardowej biblioteki”, czy jest to coś innego, ale myślę, że wygląda to ładniej. To może być dziwne, biorąc pod uwagę, że dopiero niedawno dostałem się do C ++ (używałem i nadal gram w C i innych językach znacznie dłużej, a C jest moim ulubionym językiem wszechczasów, zaraz po asemblerze).Jest jeszcze jedna rzecz, chociaż jest ona nieco związana z powyższym i tym, na co wskazują inni. Chociaż może to być złą praktyką, czasami rezerwuję
std::name
standardową wersję biblioteki i nazwę dla implementacji specyficznej dla programu. Tak, może to cię ugryźć i mocno ugryźć, ale wszystko sprowadza się do tego, że rozpocząłem ten projekt od zera i jestem jedynym programistą. Przykład: przeciążamstd::string
i nazywam tostring
. Mam pomocne dodatki. Zrobiłem to częściowo z powodu mojej skłonności do C i Unixa (+ Linux) do małych liter.Poza tym możesz mieć aliasy przestrzeni nazw. Oto przykład przydatnego zastosowania, do którego nie można było się odwoływać. Korzystam ze standardu C ++ 11, a konkretnie z libstdc ++. Cóż, nie ma pełnego
std::regex
wsparcia. Jasne, kompiluje się, ale zgłasza wyjątek w postaci błędu po stronie programisty. Ale to brak wdrożenia.Oto jak to rozwiązałem. Zainstaluj regex Boosta i połącz go. Następnie wykonuję następujące czynności, aby po całkowitym wdrożeniu libstdc ++ potrzebowałem tylko usunąć ten blok, a kod pozostanie taki sam:
Nie będę się kłócił, czy to zły pomysł, czy nie. Będę jednak argumentować, że utrzymuje go w czystości dla mojego projektu, a jednocześnie czyni go konkretnym: To prawda, muszę użyć Boosta, ale używam go tak, jakby libstdc ++ go w końcu miał. Tak, rozpoczęcie własnego projektu i rozpoczęcie od standardowego (...) na samym początku bardzo pomaga w utrzymaniu, rozwoju i we wszystkim, co jest związane z projektem!
Żeby coś wyjaśnić: nie sądzę, że dobrym pomysłem jest używanie nazwy klasy / czegokolwiek w STL celowo i bardziej konkretnie zamiast. Ciąg jest dla mnie wyjątkiem (zignoruj pierwszy, powyżej lub drugi tutaj, pun, jeśli musisz) dla mnie, ponieważ nie podobał mi się pomysł „String”.
W tej chwili jestem nadal bardzo stronniczy w stosunku do C i stronniczy w stosunku do C ++. Oszczędzanie szczegółów, większość tego, nad czym pracuję, bardziej pasuje do C (ale było to dobre ćwiczenie i dobry sposób, aby a. Nauczyć się innego języka i b. Starać się nie być mniej stronniczy w stosunku do obiektów / klas / itp., Co może lepiej powiedzieć jako mniej zamknięte, mniej aroganckie i bardziej akceptujące). Ale to, co jest użyteczne, co niektórzy już zaproponował: I rzeczywiście używają listy (jest dość ogólny, prawda?), A sort (samo), aby wymienić tylko dwa, które spowodowałyby nazwę starcia gdybym miał zrobić
using namespace std;
, i tak w tym celu wolę być konkretny, kontrolować i wiedząc, że jeśli zamierzam być standardowym zastosowaniem, będę musiał to określić. Mówiąc wprost: żadne założenie nie jest dozwolone.A jeśli chodzi o włączenie wyrażenia regularnego Boost
std
. Robię to w celu przyszłej integracji i - ponownie, w pełni przyznam, że to stronniczość - nie sądzę, aby było tak brzydkie jakboost::regex:: ...
. Rzeczywiście, to dla mnie kolejna rzecz. W C ++ jest wiele rzeczy, które muszę jeszcze zaakceptować w wyglądzie i metodach (inny przykład: szablony variadic kontra var argumenty [choć przyznaję, że szablony variadic są bardzo przydatne!]). Nawet te, które akceptuję, były trudne i nadal mam z nimi problemy.źródło
std
przestrzeni nazw jest zachowaniem niezdefiniowanym i dlatego nigdy nie powinno się tego robić.Z moich doświadczeń wynika, że jeśli masz wiele bibliotek, które używają powiedz
cout
, ale w innym celu możesz użyć złegocout
.Na przykład, jeśli wpisam,
using namespace std;
ausing namespace otherlib;
i wpisz po prostucout
(co dzieje się w obu), zamiaststd::cout
(lub'otherlib::cout'
), możesz użyć złego, i pojawiają się błędy. Jest o wiele bardziej skuteczny i wydajny w użyciustd::cout
.źródło
W przypadku niekwalifikowanych importowanych identyfikatorów potrzebujesz zewnętrznych narzędzi wyszukiwania, takich jak grep, aby dowiedzieć się, gdzie identyfikowane są identyfikatory. Utrudnia to rozumowanie na temat poprawności programu.
źródło
To zależy od tego, gdzie się znajduje. Jeśli jest to wspólny nagłówek, to zmniejszasz wartość przestrzeni nazw, scalając ją z globalną przestrzenią nazw. Pamiętaj, że może to być fajny sposób na tworzenie globałów modułowych.
źródło
Jest to zła praktyka, często znana jako globalne zanieczyszczenie przestrzeni nazw. Problemy mogą wystąpić, gdy więcej niż jedna przestrzeń nazw ma tę samą nazwę funkcji z podpisem, wówczas kompilator nie będzie mógł zdecydować, który z nich wywołać, a tego wszystkiego można uniknąć, określając przestrzeń nazw za pomocą wywołania funkcji
std::cout
. Mam nadzieję że to pomoże. :)źródło
Aby odpowiedzieć na twoje pytanie, patrzę na to w ten sposób praktycznie: wielu programistów (nie wszyscy) wywołuje przestrzeń nazw std. Dlatego należy przyzwyczaić się NIE używać rzeczy, które wpływają lub używają tych samych nazw, co w std przestrzeni nazw. To wielka sprawa, ale nie tyle w porównaniu z liczbą możliwych spójnych słów i pseudonimów, które można wymyślić ściśle.
Mam na myśli naprawdę ... powiedzenie „nie polegaj na tym, że jesteś obecny” oznacza po prostu ustawienie się na poleganie na tym, że NIE jest obecny. Ciągle będziesz mieć problemy z pożyczaniem fragmentów kodu i ciągłą ich naprawą. Po prostu trzymaj swoje zdefiniowane przez użytkownika i pożyczone rzeczy w ograniczonym zakresie, tak jak powinny, i BARDZO oszczędzaj z globalsami (szczerze mówiąc, globals prawie zawsze powinny być ostatecznością w celu „skompiluj teraz, rozsądek później”). Naprawdę myślę, że to zła rada od twojego nauczyciela, ponieważ użycie std będzie działać zarówno dla „cout”, jak i „std :: cout”, ale NIE użycie std będzie działać tylko dla „std :: cout”. Nie zawsze będziesz miał szczęście, aby napisać cały swój kod.
UWAGA: Nie skupiaj się zbytnio na problemach z wydajnością, dopóki nie dowiesz się trochę o tym, jak działają kompilatory. Przy odrobinie doświadczenia w kodowaniu nie musisz się dużo o nich uczyć, zanim zdasz sobie sprawę, ile potrafią uogólnić dobry kod w coś prostego. Wszystko jest tak proste, jakbyś napisał całość w C. Dobry kod jest tak skomplikowany, jak powinien.
źródło
<algorithm>
na przykład wymyślając na nowo rzeczy ), wydaje się nieco trudniej wyobrazić sobie, że ci sami ludzie mogliby niezawodnie unikać tych identyfikatorów. Przejrzyj własny kod i powiedz mi, że nigdy nie masz wywołanej zmiennej lub funkcjicount
. Albodistance
, albolog
,destroy
,launch
,visit
,beta
,sample
,messages
,clamp
,erase
,copy
,modulus
,left
, itd. Nie wspominając wszystkie identyfikatory nie są jeszcze wstd
który złamie kod C ++ 35, gdy wychodzi ...