Dlaczego "używanie przestrzeni nazw std;" jest uważane za złą praktykę?

Powiedziano mi przez innych, że pisanie using namespace std; w kodzie jest złe i że powinienem używać std::cout i std::cin bezpośrednio zamiast tego.

Dlaczego using namespace std; jest uważana za złą praktykę? Czy jest to nieefektywne, czy też istnieje ryzyko deklarowania zmiennych niejednoznacznych (zmiennych o tej samej nazwie co funkcja w przestrzeni nazw std)? Czy ma to wpływ na wydajność?

Author: L. F., 2009-09-21

30 answers

Nie jest to w ogóle związane z wydajnością. Ale rozważ to: używasz dwóch bibliotek o nazwie Foo i Bar:

using namespace foo;
using namespace bar;

Wszystko działa dobrze, i możesz bez problemów dzwonić Blah() z Foo i Quux() Z Baru. Ale pewnego dnia można uaktualnić do nowej wersji Foo 2.0, który oferuje teraz funkcję o nazwie Quux(). Teraz masz konflikt: zarówno Foo 2.0, jak i bar import Quux() do globalnej przestrzeni nazw. Naprawienie tego wymaga trochę wysiłku, zwłaszcza jeśli parametry funkcji dopasować.

Jeśli użyłbyś foo::Blah() i bar::Quux(), to wprowadzenie foo::Quux() nie byłoby wydarzeniem.

 2397
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 22:23:42

Zgadzam się ze wszystkim Greg napisał , ale chciałbym dodać: Może być nawet gorzej niż powiedział Greg!

Biblioteka Foo 2.0 może wprowadzić funkcję, Quux(), która jest jednoznacznie lepsza dla niektórych wywołań do Quux() niż bar::Quux() Kod wywoływany przez lata. Wtedy twój kod wciąż kompiluje, Ale po cichu wywołuje złą funkcję i robi Bóg wie co. To jest tak złe, jak to tylko możliwe. get.

Należy pamiętać, że przestrzeń nazw std ma mnóstwo identyfikatorów, z których wiele to bardzo zwykłe (think list, sort, string, iterator, itd.), które najprawdopodobniej pojawią się także w innych kodach.

Jeśli uznasz to za mało prawdopodobne: było pytanie zadane tutaj na Stack Overflow, gdzie prawie dokładnie to się stało (zła funkcja wywołana z powodu pominiętego prefiksu std::) około pół roku po udzieleniu tej odpowiedzi. tutaj jest inny, więcej niedawny przykład takiego pytania. Więc to jest prawdziwy problem.


Oto jeszcze jeden punkt danych: wiele, wiele lat temu, ja również uważałem za denerwujące, że muszę przedrostkować wszystko z biblioteki standardowej za pomocą std::. Potem pracowaĹ ' em w projekcie, w ktĂłrym na poczÄ ... tku zdecydowano, Ĺźe zarĂłwno using dyrektywy jak i deklaracje sÄ ... zakazane z wyjÄ ... tkiem zakresăłw funkcyjnych. Wiesz co? Większość z nas przyzwyczaiła się do pisania przedrostka kilka tygodni, a po kilku tygodniach większość z nas nawet zgodził się, że w rzeczywistości kod stał się bardziej czytelny . Jest ku temu powód: Czy lubisz krótszą czy dłuższą prozę jest subiektywna, ale przedrostki obiektywnie dodają wyrazistości kodowi. nie tylko kompilator, ale i Ty łatwiej widzisz, do którego identyfikatora się odnosi.

W ciągu dekady projekt ten urósł do kilku milionów linii kodu. Ponieważ te dyskusje pojawiają się raz po raz, byłem kiedyś ciekaw, jak często (dozwolone) function-scope using faktycznie została użyta w projekcie. Sprawdziłem źródła i znalazłem tylko 1-2 tuziny miejsc, w których był używany. Dla mnie oznacza to, że po wypróbowaniu programiści nie znajdują std:: wystarczająco bolesnych, aby używać dyrektyw nawet raz na 100 kLoC, nawet tam, gdzie było to dozwolone.


Podsumowując: jednoznaczne poprzedzanie wszystkiego nie wyrządza żadnej szkody, zajmuje bardzo mało przyzwyczajenia i ma obiektywne zalety. W szczególności sprawia, że kod łatwiejsze do zinterpretowania przez kompilator i przez ludzkich czytelników - i to powinno być chyba głównym celem przy pisaniu kodu.

 1457
Author: sbi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-27 20:31:03

Problem z umieszczaniem using namespace w plikach nagłówkowych Twoich klas polega na tym, że zmusza to każdego, kto chce używać twoich klas (włączając pliki nagłówkowe) do "używania" (tzn. widząc wszystko w) tych innych przestrzeniach nazw.

Możesz jednak śmiało umieścić w swoim (prywatnym) *wypowiedź using.pliki cpp.


Uwaga, że niektórzy nie zgadzają się z moim powiedzeniem "feel free" w ten sposób-bo chociaż using oświadczenie w pliku cpp jest lepsze niż w nagłówek (ponieważ nie wpływa na ludzi, którzy dołączają Twój plik nagłówkowy), uważają, że nadal nie jest on dobry (ponieważ w zależności od kodu może to utrudnić utrzymanie implementacji klasy). ten wpis C++ Super-FAQ mówi:

Using-directive istnieje dla starszego kodu C++ i aby ułatwić przejście do przestrzeni nazw, ale prawdopodobnie nie powinieneś używać jej regularnie, przynajmniej nie w swoim nowym kodzie C++.

FAQ sugeruje dwie alternatywy:

  • A using-declaration:

    using std::cout; // a using-declaration lets you use cout without qualification
    cout << "Values:";
    
  • Just typing std::

    std::cout << "Values:";
    
 466
Author: ChrisW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-30 03:54:15

Ostatnio natknąłem się na skargę na Visual Studio 2010. Okazało się, że prawie wszystkie pliki źródłowe miały te dwie linie:

using namespace std;
using namespace boost;

Wiele funkcji Boost wchodzi do standardu C++0x, a Visual Studio 2010 ma wiele funkcji C++0x, więc nagle te programy nie były kompilowane.

Dlatego unikanie using namespace X; jest formą przyszłościowego sprawdzania, sposobem upewnienia się, że zmiana używanych bibliotek i / lub plików nagłówkowych nie spowoduje złamania program.
 246
Author: David Thornley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-11 10:33:18

Skrócona wersja: nie używaj globalnych deklaracji ani dyrektyw using w plikach nagłówkowych. Możesz ich używać w plikach implementacyjnych. Oto coHerb Sutter iAndrei Alexandrescu mają do powiedzenia na ten temat wC++ Coding Standards (pogrubienie dla podkreślenia jest moje):

Podsumowanie

Użycie przestrzeni nazw jest dla Twojej wygody, a nie dla Ciebie do zadawania innym: nigdy nie pisz using declaration lub using directive przed # include dyrektywa.

Corollary: w plikach nagłówkowych, nie zapisuj poziomu przestrzeni nazw za pomocą dyrektyw lub deklaracji; zamiast tego, jawnie przestrzeń nazw-kwalifikuje wszystkie nazwy. (Druga reguła wynika z pierwszej, ponieważ nagłówki nigdy nie mogą wiedzieć, co zawiera inny nagłówek#, może pojawić się po nich.)

Dyskusja

W skrócie: możesz i powinieneś używać przestrzeni nazw używając deklaracji i dyrektyw w swoich plikach implementacyjnych po # include directives i czuć się z tym dobrze. pomimo powtarzających się twierdzeń, że jest inaczej, przestrzeń nazw używająca deklaracji i dyrektyw nie jest zła i nie narusza celu przestrzeni nazw. Są one raczej tym, co czyni przestrzenie nazw użytecznymi .

 217
Author: mattnewport,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Nie powinno siÄ ™ uĺźywaä ‡ dyrektywy using w zakresie globalnym, zwĹ 'aszcza w nagĹ' ăłwkach. Jednak są sytuacje, w których jest to właściwe nawet w pliku nagłówkowym:

template <typename FloatType> inline
FloatType compute_something(FloatType x)
{
    using namespace std; // No problem since scope is limited
    return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));
}

To jest lepsze niż jednoznaczna kwalifikacja (std::sin, std::cos...), ponieważ jest krótszy i ma możliwość pracy z typami zmiennoprzecinkowymi zdefiniowanymi przez użytkownika (poprzez wyszukiwanie zależne od argumentów (ADL)).

 131
Author: robson3.14,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 22:37:20

Nie używaj go globalnie

Jest uważany za "zły" tylko wtedy, gdy jest używany globalnie . Ponieważ:

  • zaśmiecasz przestrzeń nazw, w której programujesz.
  • czytelnicy będą mieli trudności z rozpoznaniem, skąd pochodzi dany identyfikator, gdy użyjesz wielu using namespace xyz.
  • cokolwiek jest prawdą dla innych czytających Twój kod źródłowy jest tym bardziej prawdziwe dla najczęściej czytającego: Ciebie. Wróć za rok lub dwa i weź spójrz...
  • jeśli mówisz tylko o 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 uzyskać konflikty nazw, których nie byłeś świadomy.

Można go używać lokalnie

Śmiało i używaj go lokalnie (prawie) swobodnie. To, oczywiście, zapobiega powtarzaniu std:: -- i powtarzanie jest również złe.

Idiom do używania go lokalnie

W C++03 był idiom -- boilerplate kod -- do implementacji swap funkcji dla Twoich klas. Zasugerowano, aby rzeczywiście użyć lokalnego using namespace std -- lub przynajmniej using std::swap:

class Thing {
    int    value_;
    Child  child_;
public:
    // ...
    friend void swap(Thing &a, Thing &b);
};
void swap(Thing &a, Thing &b) {
    using namespace std;      // make `std::swap` available
    // swap all members
    swap(a.value_, b.value_); // `std::stwap(int, int)`
    swap(a.child_, b.child_); // `swap(Child&,Child&)` or `std::swap(...)`
}

Robi to następującą magię:

  • kompilator wybierze std::swap dla value_, tzn. void std::swap(int, int).
  • jeśli masz przeciążenie void swap(Child&, Child&) zaimplementowany kompilator wybierze go.
  • Jeśli nie masz tego przeciążenia kompilator użyje void std::swap(Child&,Child&) i spróbuje jak najlepiej je wymienić.

Z C++11 nie ma już powodu, aby używać tego wzoru. Implementacja std::swap została zmieniona, aby znaleźć potencjalne przeciążenie i wybrać je.

 101
Author: towi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-06 07:35:50

Jeśli importujesz odpowiednie pliki nagłówkowe, nagle masz takie nazwy jak hex, left, plus lub count w Twoim globalnym zasięgu. Może to być zaskakujące, jeśli nie wiesz, że std:: zawiera te nazwy. Jeśli spróbujesz używać tych nazw lokalnie, może to prowadzić do pewnego zamieszania.

Jeśli wszystkie standardowe rzeczy są w swojej własnej przestrzeni nazw, nie musisz się martwić o kolizje nazw z kodem lub innymi bibliotekami.

 82
Author: sth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-31 22:17:41

Innym powodem jest zaskoczenie.

Jeśli widzę cout << blah, zamiast std::cout << blah myślę: co to jest cout? Czy to normalne cout? Czy to coś wyjątkowego?

 53
Author: Martin Beckett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 22:24:21

Doświadczeni programiści używają tego, co rozwiązuje ich problemy i unikają tego, co tworzy nowe problemy, i unikają używania dyrektyw 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. Drobnym powodem tego jest to, że nie jest elegancko pisać więcej kodu, gdy wystarcza mniej kodu , chyba że istnieją dobre powody . Głównym powodem tego jest wyłączenie wyszukiwania zależnego od argumentów ADL).

Jakie są tedobre powody ? Czasami programiści wyraźnie chcą wyłączyć ADL, innym razem chcą disambiguate.

Więc następujące są OK:

  1. na poziomie funkcji używanie dyrektyw i deklaracji wewnątrz implementacji funkcji
  2. Source-file-level using-declarations inside source files
  3. (czasami) source-file-level using-directives
 48
Author: Alexander Poluektov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-16 20:53:41

Zgadzam się, że nie powinno być używane globalnie, ale nie jest tak źle używać lokalnie, jak w namespace. Oto przykład z " języka programowania C++ ":

namespace My_lib {

    using namespace His_lib; // Everything from His_lib
    using namespace Her_lib; // Everything from Her_lib

    using His_lib::String; // Resolve potential clash in favor of His_lib
    using Her_lib::Vector; // Resolve potential clash in favor of Her_lib

}

W tym przykładzie rozwiązaliśmy potencjalne starcia nazw i niejasności wynikające z ich składu.

Nazwy jawnie zadeklarowane (w tym nazwy zadeklarowane przez deklaracje using-jak His_lib::String) mają pierwszeństwo przed nazwami udostępnionymi w innym zakresie przez dyrektywę using-(using namespace Her_lib).

 47
Author: Oleksiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 22:53:02

Ja również uważam to za złą praktykę. Dlaczego? Pewnego dnia pomyślałem, że funkcją przestrzeni nazw jest dzielenie rzeczy, więc nie powinienem tego zepsuć wrzuceniem wszystkiego do jednego worka.

Jeśli jednak często używam 'cout' i 'cin', piszę: using std::cout; using std::cin; w .plik cpp (nigdy w pliku nagłówkowym, ponieważ propaguje się przez #include). Myślę, że nikt przy zdrowych zmysłach nigdy nie nazwie strumienia cout lub cin. ;)

 32
Author: Yelonek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 22:35:59

Miło widzieć kod i wiedzieć, co robi. Jeśli widzę std::cout wiem, że to jest cout strumień std biblioteki. Jeśli zobaczę cout to nie wiem. To Może być strumieniem cout biblioteki std. Albo może być int cout = 0; dziesięć linii wyżej w tej samej funkcji. Lub zmienną static o nazwie cout w tym pliku. To może być cokolwiek.

Teraz weź bazę kodu miliona linii, która nie jest szczególnie duża, i szukasz błędu, co oznacza, że wiesz, że istnieje jeden linia w tym milionie linii, która nie robi tego, co powinna. cout << 1; może odczytać static int o nazwie cout, przesunąć ją w lewo o jeden bit i wyrzucić wynik. Szukając pluskwy, muszę to sprawdzić. Widzisz, jak naprawdę wolę widzieć std::cout?

To jedna z tych rzeczy, która wydaje się być naprawdę dobrym pomysłem, jeśli jesteś nauczycielem i nigdy nie musisz pisać i utrzymywać żadnego kodu. Uwielbiam widzieć Kod, gdzie (1) wiem, co robi; i (2) jestem przekonany, że osoba pisząca to wiedziała, co robi.
 27
Author: gnasher729,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-29 12:47:01

Chodzi o zarządzanie złożonością. Korzystanie z przestrzeni nazw spowoduje wciągnięcie rzeczy, których nie chcesz, a tym samym prawdopodobnie utrudni debugowanie (mówię, że możliwe). Używanie STD:: wszędzie jest trudniejsze do odczytania(więcej tekstu i tym podobne).

Konie na kursy-Zarządzaj swoją złożonością tak, jak najlepiej Możesz i czujesz się w stanie.

 25
Author: Preet Sangha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-25 19:40:31

Rozważ

// myHeader.h
#include <sstream>
using namespace std;


// someoneElses.cpp/h
#include "myHeader.h"

class stringstream {  // Uh oh
};

Zauważ, że jest to prosty przykład. Jeśli masz pliki z 20 includes i innymi importami, będziesz musiał przejść mnóstwo zależności, aby rozwiązać problem. Gorsze jest to, że możesz uzyskać niepowiązane błędy w innych modułach w zależności od definicji, które są sprzeczne.

To nie jest straszne, ale zaoszczędzisz sobie bólu głowy, nie używając go w plikach nagłówkowych lub globalnej przestrzeni nazw. To chyba w porządku zrobić to w bardzo ograniczonym lunety, ale nigdy nie miałem problemu z wpisaniem dodatkowych pięciu znaków, aby wyjaśnić, skąd pochodzą moje funkcje.

 20
Author: Ron Warholic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 22:28:01

Konkretny przykład do wyjaśnienia problemu. Wyobraź sobie sytuację, w której masz dwie biblioteki, foo i bar, każda z własną przestrzenią nazw:

namespace foo {
    void a(float) { /* Does something */ }
}

namespace bar {
    ...
}

Załóżmy, że używasz foo i bar razem w swoim własnym programie w następujący sposób:

using namespace foo;
using namespace bar;

void main() {
    a(42);
}
W tym momencie wszystko jest w porządku. Po uruchomieniu programu "coś robi". Ale później zaktualizujesz bar i powiedzmy, że zmieniło się tak:
namespace bar {
    void a(float) { /* Does something completely different */ }
}

W tym momencie otrzymasz kompilator błąd:

using namespace foo;
using namespace bar;

void main() {
    a(42);  // error: call to 'a' is ambiguous, should be foo::a(42)
}

Więc musisz zrobić trochę konserwacji, aby wyjaśnić, że " a " oznaczało foo::a. Jest to niepożądane, ale na szczęście jest to dość łatwe (wystarczy dodać foo:: przed wszystkimi wywołaniami a, że kompilator zaznacza jako niejednoznaczny).

Ale wyobraź sobie alternatywny scenariusz, w którym bar zmienił się, aby wyglądać tak:

namespace bar {
    void a(int) { /* Does something completely different */ }
}

W tym momencie twoje wezwanie do a(42) nagle wiąże się z bar::a zamiast foo::a i zamiast robić 'coś' robi ' coś zupełnie inaczej". Żadnych ostrzeżeń kompilatora. Twój program po cichu zaczyna robić coś zupełnie innego niż wcześniej.

Kiedy używasz przestrzeni nazw, ryzykujesz taki scenariusz, dlatego ludzie nie lubią używać przestrzeni nazw. Im więcej rzeczy w przestrzeni nazw, tym większe ryzyko konfliktu, więc ludzie mogą być jeszcze bardziej niewygodni przy użyciu przestrzeni nazw {16]} (ze względu na liczbę rzeczy w tej przestrzeni) niż w innych przestrzeniach nazw.

Ostatecznie jest to kompromis między możliwością zapisu a niezawodnością/konserwacją. Czytelność może mieć również wpływ na to, ale widzę argumenty za tym w obu kierunkach. Normalnie powiedziałbym, że niezawodność i konserwowalność są ważniejsze, ale w tym przypadku będziesz stale płacić koszty pisowalności za dość rzadki wpływ niezawodności / konserwacji. "Najlepszy" kompromis zadecyduje o Twoim projekcie i Twoich priorytetach.

 19
Author: Kevin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-20 13:51:35

Używanie wielu przestrzeni nazw w tym samym czasie jest oczywiście receptą na katastrofę, ale używanie tylko przestrzeni nazw std i tylko przestrzeni nazw std nie jest moim zdaniem tak wielką sprawą, ponieważ redefinicja może nastąpić tylko przez twój własny kod...

Więc po prostu potraktuj je jako zastrzeżone nazwy, takie jak " int " lub "class" i to wszystko.

Ludzie powinni przestać być tak analni. Twój nauczyciel miał rację. Wystarczy użyć jednej przestrzeni nazw; to jest cały sens używania przestrzeni nazw pierwsze miejsce. Nie wolno używać więcej niż jednego w tym samym czasie. Chyba, że jest twoja. Więc ponownie, redefinicja nie nastąpi.
 18
Author: user2645752,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-11 10:44:02
  1. Musisz być w stanie odczytać kod napisany przez ludzi, którzy mają inny styl i najlepsze praktyki niż ty.

  2. Jeśli używasz tylko cout, nikt się nie myli. Ale kiedy masz wiele przestrzeni nazw latających wokół i widzisz tę klasę i nie jesteś dokładnie pewien, co ona robi, mając przestrzeń nazw jawne działa jako komentarz rodzaju. Na pierwszy rzut oka widać, "Och, to jest operacja systemu plików" lub "to robi rzeczy sieciowe".

 18
Author: Dustin Getz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 22:30:48

Zgadzam się z innymi tutaj, ale chciałbym odnieść się do obaw dotyczących czytelności - możesz tego uniknąć po prostu używając typedefów na górze swojego 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 jest okazją do przypisania nazwy, która jest znacząca w kontekście klasy. To faktycznie pomaga czytelność w definicjach klasy metody.

// Header
class File
{
   typedef std::vector<std::string> Lines;
   Lines ReadLines();
}

I w realizacji:

// .cpp
Lines File::ReadLines()
{
    Lines lines;
    // Get them...
    return lines;
}

W przeciwieństwie do:

// .cpp
vector<string> File::ReadLines()
{
    vector<string> lines;
    // Get them...
    return lines;
}

Lub:

// .cpp
std::vector<std::string> File::ReadLines()
{
    std::vector<std::string> lines;
    // Get them...
    return lines;
}
 14
Author: Carl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 23:08:19

Przestrzeń nazw jest obszarem nazwanym. Przestrzenie nazw są używane do grupowania powiązanych deklaracji i do utrzymywania oddzielnych pozycje osobno. Na przykład dwie oddzielnie opracowane biblioteki mogą używać tej samej nazwy, aby odnosić się do różnych elementy, ale użytkownik może nadal używać obu:

namespace Mylib{
    template<class T> class Stack{ /* ... */ };
    // ...
}

namespace Yourlib{
    class Stack{ /* ... */ };
    // ...
}

void f(int max) {
    Mylib::Stack<int> s1(max); // Use my stack
    Yourlib::Stack    s2(max); // Use your stack
    // ...
}

Powtarzanie nazwy przestrzeni nazw może rozpraszać zarówno czytelników, jak i pisarzy. W związku z tym możliwe jest aby stwierdzić, że nazwy z określonej przestrzeni nazw są dostępne bez wyraźnej kwalifikacji. Na przykład:

void f(int max) {
    using namespace Mylib; // Make names from Mylib accessible
    Stack<int> s1(max); // Use my stack
    Yourlib::Stack s2(max); // Use your stack
    // ...
}

Przestrzenie nazw stanowią potężne narzędzie do zarządzania różnymi bibliotekami i różnymi wersjami kodu. W szczególności, oferują programistom alternatywy dotyczące tego, jak wyraźne jest odwoływanie się do nazwy nielokalnej.

Źródło: przegląd języka programowania C++ Autor: Bjarne Stroustrup

 14
Author: Rohan Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 23:11:22

Przykład, w którym using namespace std wyrzuca błąd kompilacji z powodu niejednoznaczności count, która jest również funkcją w bibliotece algorytmów.

#include <iostream>
#include <algorithm>

using namespace std;

int count = 1;
int main() {
    cout << count << endl;
}
 12
Author: Nithin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-30 15:40:20

To nie pogarsza wydajności oprogramowania lub projektu. Włączenie przestrzeni nazw na początku kodu źródłowego nie jest złe. Dołączenie instrukcji using namespace std różni się w zależności od twoich potrzeb i sposobu, w jaki rozwijasz oprogramowanie lub projekt.

namespace std zawiera standardowe funkcje i zmienne C++. Ta przestrzeń nazw jest przydatna, gdy często używasz standardowych funkcji C++.

Jak wspomniano na tej stronie :

Instrukcja używająca przestrzeni nazw std jest ogólnie uważana za złą praktyka. Alternatywą dla tego stwierdzenia jest określenie przestrzeń nazw, do której należy identyfikator przy użyciu operatora scope(::) za każdym razem deklarujemy Typ.

I patrz ta opinia :

Nie ma problemu z użyciem "using namespace std" w pliku źródłowym kiedy intensywnie korzystasz z przestrzeni nazw i wiesz na pewno, że nic się nie zderzy.

Niektórzy ludzie mówili błędną praktyką jest umieszczanie using namespace std w plikach źródłowych, ponieważ wywołasz z tej przestrzeni nazw wszystkie funkcje i zmienne. Gdy chcesz zdefiniować nową funkcję o tej samej nazwie co inną funkcję zawartą w namespace std, przeciążasz funkcję i może ona powodować problemy z powodu kompilacji lub wykonania. Nie będzie kompilowany ani wykonywany zgodnie z oczekiwaniami.

Jak wspomniano na tej stronie :

Chociaż stwierdzenie ratuje nas od typowanie std:: wherever chcemy uzyskać dostęp do klasy lub typu zdefiniowanego w przestrzeni nazw std, to importuje całą przestrzeń nazw std do bieżącej przestrzeni nazw programu. Weźmy kilka przykładów, aby zrozumieć, dlaczego to może nie być tak dobrze

...

Teraz na późniejszym etapie rozwoju, chcemy użyć innej wersji cout, który jest niestandardowo zaimplementowany w jakiejś bibliotece o nazwie " foo " (dla przykład)

...

Zauważ jak tam jest dwuznaczność, do której biblioteki wskazuje cout? Kompilator może to wykryć, a nie skompilować program. W najgorszym przypadku, program może jeszcze skompilować, ale wywołać złą funkcję, ponieważ nigdy nie okreĹ "liliĺ" my, do ktĂłrej przestrzeni nazw naleĹźy identyfikator.

 10
Author: CryogenicNeo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 23:37:55

Nie sądzę, że jest to koniecznie zła praktyka w każdych warunkach, ale trzeba być ostrożnym, gdy go używasz. Jeśli piszesz bibliotekę, prawdopodobnie powinieneś użyć operatorów rozdzielczości zakresu z przestrzenią nazw, aby Twoja biblioteka nie mieszała się z innymi bibliotekami. Dla kodu poziomu aplikacji, nie widzę w nim nic złego.

 8
Author: Dr. Watson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-21 03:34:06

Zgadzam się z innymi-to prośba o starcia nazw, niejasności, a potem fakt jest mniej wyraźny. Chociaż widzę użycie using, moją osobistą preferencją jest ograniczenie tego. Chciałbym również mocno rozważyć to, co niektórzy inni wskazali:

Jeśli chcesz znaleźć nazwę funkcji, która może być dość popularna, ale chcesz ją znaleźć tylko w przestrzeni nazw std (lub odwrotnie – chcesz zmienić wszystkie wywołania, które są , a nie w przestrzeni nazw std, przestrzeni nazw X, ...), więc jak proponujesz to zrobić?

Mógłbyś napisać program do tego, ale czy nie byłoby lepiej poświęcić czas na pracę nad samym projektem, zamiast pisać program do utrzymania projektu?

Osobiście nie mam nic przeciwko prefiksowi std::. Bardziej podoba mi się to spojrzenie niż jego brak. Nie wiem, czy to dlatego, że jest wyraźne i mówi do mnie "to nie jest mój kod... Korzystam z biblioteki standardowej " lub jeśli jest to coś innego, ale myślę, że wygląda ładniej. To może być dziwne, biorąc pod uwagę, że dopiero niedawno dostałem się do C++ (używane i nadal zrobić C i innych języków znacznie dłużej i C jest moim ulubionym językiem wszech czasów, tuż nad assembly).

Jest jeszcze jedna rzecz, chociaż jest ona nieco związana z powyższym i tym, co inni wskazują. Chociaż może to być zła praktyka, czasami rezerwuję std::name dla standardowej wersji biblioteki i nazwy dla implementacji specyficznych dla programu. Tak, to może cię ugryźć i mocno ugryźć, ale to wszystko przychodzi do tego zacząłem ten projekt od zera i jestem do tego jedynym programistą. Przykład: i overload std::string and call it string. Mam pomocne dodatki. Zrobiłem to częściowo z powodu mojej C i Unix (+ Linux) skłonności do małych liter.

Poza tym, możesz mieć aliasy przestrzeni nazw. Oto przykład, gdzie jest to przydatne, które nie zostały wymienione. Używam standardu C++11, a konkretnie z libstdc++. Cóż, nie ma pełnego std::regex wsparcia. Jasne. kompiluje, ale rzuca wyjątek w taki sposób, że jest to błąd na końcu 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 gdy libstdc++ ma ją zaimplementowaną w całości, muszę tylko usunąć ten blok, A kod pozostaje taki sam:

namespace std
{
    using boost::regex;
    using boost::regex_error;
    using boost::regex_replace;
    using boost::regex_search;
    using boost::regex_match;
    using boost::smatch;
    namespace regex_constants = boost::regex_constants;
}
Nie będę się spierał, czy to zły pomysł, czy nie. Będę jednak twierdził, że utrzymuje go w czystości dla mój projekt i w tym samym czasie czyni go specyficznym: prawda, muszę użyć Boost, ale używam go tak, jak libstdc++ w końcu go będzie miał. Tak, rozpoczynając własny projekt i zaczynając od standardu (...) na samym początku idzie bardzo długą drogę z pomocą w utrzymaniu, rozwoju i wszystko, co związane z projektem!

Żeby coś wyjaśnić: nie uważam za dobry pomysł używać nazwy klasy/cokolwiek w STL celowo, a dokładniej w miejsce. Ciąg jest wyjątkiem (zignoruj pierwszy, powyżej lub drugi tutaj, kalambur, jeśli musisz) Dla mnie, ponieważ nie podoba mi się pomysł 'String'.

Jak to jest, nadal jestem bardzo stronniczy wobec C i stronniczy wobec c++. Oszczędne szczegóły, wiele z tego, nad czym pracuję, pasuje bardziej do C (ale to było dobre ćwiczenie i dobry sposób, aby się a. nauczyć się innego języka i b. staraj się nie być mniej stronniczy wobec przedmiotów/klas / itp. akceptuję.). Ale to, co jest użyteczne, jest tym, co niektórzy już zasugerowali: rzeczywiście używam listy (jest dość ogólna, prawda ?), i sortuj (to samo), aby wymienić dwa, które spowodowałyby konflikt nazw, gdybym miał to zrobić using namespace std;, a więc w tym celu wolę być konkretny, kontrolowany i wiedząc, że jeśli zamierzam to być standardowym użyciem, będę musiał to określić. Mówiąc prościej: nie wolno zakładać.

I co do robienia Boost ' S regex części std. Robię to dla przyszłej integracji i – ponownie, przyznaję w pełni, że to stronniczość - nie sądzę, że jest tak brzydka jak boost::regex:: .... W rzeczy samej, to dla mnie inna sprawa. Jest wiele rzeczy w C++ , które muszę jeszcze w pełni zaakceptować w wyglądzie i metodach (inny przykład: variadic templates versus var arguments [choć przyznaję, że variadic templates są bardzo przydatne!]). Nawet te, które akceptuję, były trudne, i nadal mam z nimi problemy.

 8
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 23:03:03

Z moich doświadczeń wynika, że jeśli masz wiele bibliotek, które używają powiedzmy, cout, ale w innym celu możesz użyć niewłaściwego cout.

Na przykład, jeśli wpiszę using namespace std; i using namespace otherlib; i napiszę tylko cout (co zdarza się w obu), zamiast std::cout (lub 'otherlib::cout'), możesz użyć niewłaściwego i uzyskać błędy. Jest znacznie bardziej efektywny i wydajny w użyciu std::cout.

 8
Author: Engine Dev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-19 23:30:12

To sprawa po sprawie. Chcemy zminimalizować "całkowity koszt posiadania" oprogramowania przez cały okres jego użytkowania. Używanie przestrzeni nazw std wiąże się z pewnymi kosztami, ale Nie używanie tej przestrzeni ma również koszty czytelności.

Ludzie poprawnie zwracają uwagę, że podczas korzystania z niej, gdy biblioteka standardowa wprowadza nowe symbole i definicje, Twój kod przestaje być kompilowany i możesz być zmuszony do zmiany nazw zmiennych. A jednak jest to prawdopodobnie dobre długoterminowo, ponieważ przyszli opiekunowie będą chwilowo zdezorientowany lub rozproszony, jeśli używasz słowa kluczowego w zaskakującym celu.

Nie chcesz mieć szablon o nazwie vector, powiedzmy, który nie jest wektorem znanym wszystkim innym. A liczba nowych definicji wprowadzonych w ten sposób w bibliotece C++ jest na tyle mała, że może po prostu nie pochodzić. Istnieje jest koszt konieczności dokonania tego rodzaju zmiany, ale koszt nie jest wysoki i jest równoważony przez jasność uzyskaną przez nieużywanie std nazw symboli dla innych cele.

Biorąc pod uwagę liczbę klas, zmiennych i funkcji, stwierdzenie std:: na każdej z nich może zwiększyć Twój kod o 50% i utrudnić zrozumienie. Algorytm lub krok w metodzie, który można wprowadzić na jednym ekranie kodu, wymaga teraz przewijania w tę i z powrotem, aby podążać za nim. To prawdziwy koszt. Prawdopodobnie nie jest to wysoki koszt, ale ludzie, którzy zaprzeczają, że w ogóle istnieje, są niedoświadczeni, dogmatyczni lub po prostu źle.

Zaproponowałbym następujące Zasady:

  1. std różni się od wszystkich innych bibliotek. Jest to jedyna biblioteka, którą w zasadzie każdy powinien znać, a moim zdaniem najlepiej jest myśleć o niej jako o części języka. Ogólnie rzecz biorąc, istnieje doskonały przypadek dla using namespace std, nawet jeśli nie ma innych bibliotek.

  2. Nigdy nie wymuszaj decyzji na autorze jednostki kompilacyjnej (a .plik cpp) poprzez umieszczenie tego using w nagłówku. zawsze odkładaj decyzję autorowi kompilacji. Nawet w projekcie, który zdecydował się używać using namespace std wszędzie może nałożyć grzywnę na kilka modułów, które najlepiej traktować jako wyjątki od tej reguły.

  3. Mimo że funkcja przestrzeni nazw pozwala mieć wiele modułów z symbolami zdefiniowanymi tak samo,będzie to mylące. Zachowaj różne nazwy w miarę możliwości. Nawet jeśli nie używasz funkcji przestrzeni nazw, jeśli masz klasę o nazwie foo i std wprowadza klasę o nazwie foo, prawdopodobnie lepiej będzie zmienić nazwę zajęcia w każdym razie.

  4. Alternatywą dla używania przestrzeni nazw jest ręczne umieszczanie symboli przestrzeni nazw poprzez ich prefiks. Mam dwie biblioteki, których używam od dziesięcioleci, obie zaczynające się jako biblioteki C, gdzie każdy symbol jest poprzedzony "AK" lub "SCWin". Ogólnie rzecz biorąc, jest to jak unikanie konstrukcji "używającej", ale nie piszesz podwójnych dwukropków. AK::foo() jest zamiast AKFoo(). To sprawia, że kod 5-10% gęstszy i mniej gadatliwy, a jedynym minusem jest to, że będziesz w dużym problem, jeśli musisz użyć dwóch takich bibliotek, które mają ten sam prefiks. Zauważ, że biblioteki X Window są doskonałe pod tym względem, z wyjątkiem tego, że zapomnieli to zrobić z kilkoma #definicjami: TRUE I FALSE powinny być XTRUE i XFALSE, a to skonfigurowało przestrzeń nazw zderzającą się z Sybase lub Oracle, które podobnie używały TRUE I FALSE z różnymi wartościami! (ASCII 0 i 1 w przypadku bazy danych!) Jedną ze szczególnych zalet tego jest to, że stosuje się je do definicji preprocesora, podczas gdy C++ using/namespace system nie radzi sobie z nimi. Miłą zaletą tego jest to, że daje organiczne nachylenie od bycia częścią projektu do ostatecznie bycia biblioteką. W dużej mojej aplikacji wszystkie klasy okien są poprzedzone prefiksem Win, wszystkie moduły przetwarzania sygnałów Mod i tak dalej. Istnieje niewielka szansa, że któryś z nich zostanie ponownie użyty, więc nie ma praktycznej korzyści z przekształcenia każdej grupy w bibliotekę, ale w ciągu kilku sekund staje się oczywiste, w jaki sposób projekt rozpada się na podprojekty.

 8
Author: Swiss Frank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-21 09:08:26

W przypadku niewykwalifikowanych zaimportowanych identyfikatorów potrzebujesz zewnętrznych narzędzi wyszukiwania, takich jak grep , aby dowiedzieć się, gdzie identyfikatory są deklarowane. To utrudnia rozumowanie o poprawności programu.

 7
Author: August Karlstrom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-11 14:22:33

To zależy gdzie się znajduje. Jeśli jest to wspólny nagłówek, to zmniejszasz wartość przestrzeni nazw, łącząc ją z globalną przestrzenią nazw. Należy pamiętać, że może to być zgrabny sposób tworzenia modułów globalnych.

 7
Author: MathGladiator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-11 10:18:06

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, wtedy będzie niejednoznaczne dla kompilatora, aby zdecydować, który z nich do wywołania i tego wszystkiego można uniknąć, gdy określasz przestrzeń nazw za pomocą wywołania funkcji, jak std::cout. Mam nadzieję, że to pomoże. :)

 7
Author: adn.911,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-30 16:24:48

Aby odpowiedzieć na twoje pytanie, patrzę na to w ten sposób praktycznie: wielu programistów (nie wszyscy) powołuje przestrzeń nazw std. Dlatego należy mieć w zwyczaju nie używać rzeczy, które uderzają lub używają tych samych nazw, co to, co jest w przestrzeni nazw std. To dużo, 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 mówiąc.

Mam na myśli naprawdę... powiedzenie "nie polegaj na tym, że jesteś obecny" to tylko ustawienie Cię do polegaj na tym, że go nie ma. Ciągle będziesz miał problemy z pożyczaniem fragmentów kodu i ciągłym ich naprawianiem. Po prostu trzymaj swoje rzeczy zdefiniowane przez użytkownika i pożyczone w ograniczonym zakresie, tak jak powinny być i być bardzo oszczędne z globalami(szczerze mówiąc globale powinny prawie zawsze być ostatecznością dla celów "skompiluj teraz, rozsądku później"). Naprawdę uważam, że jest to zła rada od nauczyciela, ponieważ używanie std będzie działać zarówno dla "cout", jak i "std:: cout", ale nie używanie std będzie działać tylko dla "std:: cout" Nie zawsze będziesz na tyle szczęśliwy, aby napisać cały swój własny kod.

Uwaga: nie skupiaj się zbytnio na kwestiach wydajności, dopóki nie dowiesz się trochę o tym, jak działają Kompilatory. Przy odrobinie doświadczenia w kodowaniu nie musisz się tyle o nich uczyć, zanim zdasz sobie sprawę, jak bardzo są w stanie uogólnić dobry kod na coś prostego. Każdy bit jest tak prosty, jak gdybyś napisał całość w C. dobry kod jest tylko tak złożony, jak musi być.

 6
Author: Noneyo Getit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-27 20:33:03