Soru Neden “namespace std kullanıyor” kötü uygulama olarak değerlendiriliyor?


Başkaları tarafından yazıldığını söyledim using namespace std kod yanlıştır ve kullanmam gerekir std::cout ve std::cin doğrudan yerine.

Neden ki using namespace std Kötü bir uygulama mı sayılır? Verimsiz mi yoksa belirsiz değişkenler bildirme riski mi var? (Aynı adı bir işlev olarak paylaşan değişkenler) std ad)? Performansı etkiler mi?


2069
2017-09-21 03:08


Menşei


Yapabileceğinizi unutma: "std :: cout kullanarak;" yani std :: cout yazmanız gerekmez, ancak tüm std ad alanını aynı anda getirmezsiniz. - Bill
@ ücretli inek google-styleguide.googlecode.com/svn/trunk/... bağlantı artık çalışmıyor. Yeni bağlantı gibi görünüyor google.github.io/styleguide/cppguide.html#Other_C++_Features - MCG
Başlık dosyalarındaki dosya kapsamındaki 'namespace std' komutunu kullanmak özellikle kullanışlıdır. Dosya kapsamındaki kaynak dosyalarda (* .cpp) tüm içerden sonra kullanılması, etki tek bir çeviri birimi ile sınırlı olduğundan, oldukça kötü değildir. Daha az sorunlu olan şey onu işlevler veya sınıflar içinde kullanmaktır, çünkü etkisi işlev veya sınıf kapsamıyla sınırlıdır. - sh-
Yönergeyi kullanmaktan vazgeçerim, ancak belirli ad alanları gibi std::literals::chrono_literals, Poco::Data:Keywords,Poco::Units ve edebi veya okunabilirlik hileleriyle ilgilenecek şeyler. Başlık veya uygulama dosyalarında olduğunda. Sanırım bir işlev kapsamı içinde Tamam olabilir, ama edebi ve şeyler dışında, bu yararlı değildir. - Ludovic Zenohate Lagouardette
@Jon: Özellikle namespace std ile ilgisi yok. Vurgunun "başlık dosyalarında dosya kapsamında" olması gerekiyordu. Bunu bir tavsiye olarak belirtmek için: Başlık dosyalarındaki dosya kapsamındaki "ad alanını kullanarak" (std veya diğer) kullanmayın. Uygulama dosyalarında kullanmak tamam değildir. Belirsizlik için özür dilerim. - sh-


Cevaplar:


Bu performansla hiç ilgili değil. Ama şunu düşünün: Foo ve Bar adında iki kütüphane kullanıyorsunuz:

using namespace foo;
using namespace bar;

Herşey yolunda, arayabilirsin Blah() Foo'dan ve Quux() Bar sorunları olmadan. Ama bir gün, şimdi Foo 2.0'ın yeni bir versiyonuna geçiyorsunuz. Quux(). Artık bir çatışmanız var: Hem Foo 2.0 hem de Bar içe aktarma Quux() küresel ad alanınıza. Bu, özellikle işlev parametrelerinin eşleşmesi durumunda düzeltmek için biraz çaba harcayacak.

Kullanmış olsaydın foo::Blah() ve bar::Quux()sonra giriş foo::Quux() olay dışı olurdu.


1751
2017-09-21 03:13



Her zaman Python'un "big_honkin_name bhn olarak ithal etmesini" her zaman sevdim, böylece "big_honkin_name.something" yerine "bhn.something" ifadesini kullanabilirsiniz - gerçekten yazmayı keser. C ++ böyle bir şey var mı? - paxdiablo
@Pax namespace io = boost :: dosya sistemi; - AraK
Sanırım, "düzeltmek için biraz çaba" olduğunu söyleyen şeyleri abartıyor. Yeni foo :: Quux 'un hiçbir örneğini kullanamazsınız, bu yüzden tüm mevcut kullanımlarınızı sadece bar :: Quux ile ayırın. - MattyT
Herhangi bir duyarlı kişi, nitelenmemiş adı std türleriyle çarpışan türlere sahip bir kitaplık oluşturabilir mi? - erikkallen
@ Tom'A: ile sorun #define Kendisini ad alanlarına sınırlamıyor, ancak tüm kod tabanı üzerinden çiğniyor. Ad alanı takma adı istediğiniz şeydir. - sbi


Her şeye katılıyorum Greg yazdıama eklemek istiyorum: Greg'in dediğinden bile daha kötü olabilir!

Library Foo 2.0 bir işlevi tanıtabilir Quux()Bu, bazı çağrılarınız için net bir şekilde daha iyi bir eşleşme Quux() den bar::Quux() kodunuz yıllardır aradı. O zaman senin kod hala derler, fakat sessizce yanlış işlevi çağırır ve tanrı-bilir-ne yapar. İşlerin alabileceği kadar kötü.

Unutmayın ki std ad alanı, birçoğu çok ortak olanlar list, sort, string, iteratorvb.) diğer kodlarda görünme olasılığı çok yüksektir.

Bu olasılığını düşünürseniz: bir soru sordu Burada hemen hemen tam olarak meydana gelen Stack Overflow (yanlış işlev ihmal nedeniyle çağrıldı) std:: önek) bu cevabı verdikten yaklaşık bir yıl sonra. İşte böyle bir sorunun daha yeni bir örneğidir. Yani bu gerçek bir problem.


İşte bir veri noktası daha var: Birçok yıl önce, standart kütüphaneden her şeyi önbelleğe almak zorunda kalmayı sıkıcı buluyordum. std::. Sonra başlangıçta karar verildiği bir projede çalıştım. using işlev kapsamları dışında direktifler ve beyanlar yasaklanmıştır. Bil bakalım ne oldu? Önceleri yazmak için alışmamız birkaç haftayı aldı ve birkaç hafta sonra çoğumuz kodun gerçekte yapılmasına bile karar verdi. daha okunabilir. Bunun bir nedeni var: Daha kısa veya daha uzun nesir ister öznel, isterse önekler nesnel olarak kodlara netlik katıyor. Sadece derleyici değil, aynı zamanda hangi tanımlayıcıya başvurulduğunu görmeyi daha kolay buluyorsunuz.

On yıl içinde, bu proje birkaç milyondan fazla koda sahip oldu. Bu tartışmalar tekrar tekrar gündeme geldiğinden beri, bir zamanlar (izin verilen) fonksiyon kapsamının ne kadar sık ​​olduğunu merak ettim usingaslında projede kullanıldı. Bunun için kaynakları düşünüyorum ve sadece kullanıldığı bir veya iki düzine yer buldum. Bana göre bu, bir kez denedim, geliştiriciler bulamıyor std:: 100 kLoC'de bile kullanılmasına izin verilen yerlerde bile direktifler kullanarak işe yaramaya yetecek kadar ağrılıdır.


Alt satır: Her şeyi açıkça önleyen, herhangi bir zararı yoktur, alışmak çok az alır ve objektif avantajları vardır. Özellikle, kod, derleyici tarafından ve insan okuyucular tarafından yorumlanmasını kolaylaştırır - ve bu, kod yazarken muhtemelen ana hedef olmalıdır.


1152
2017-09-21 09:26



Tek bir satırda paketleyebileceğiniz kod yoğunluğunu önemli ölçüde azaltır. Kodunuzu çok uzun bir yolla yazıyorsunuz; okunabilirliği azaltır. Şahsen, daha kısa (ama çok kısa değil) kodların daha okunabilir olma eğiliminde olduğunu düşünüyorum (çünkü okunacak daha az şey ve dikkati dağıtacak daha az şey olduğu için). - Lie Ryan
C ++ 'nın bir standardı vardı eski günlerde özledim sanırım string sınıf ve görünüşte her kütüphane kendi vardı. Ne diyeceğiz: Kodumuzu yazıyoruz. std::ve kodumuzu grep -v std:: | vim göz attığın zaman. Ya da editörünüzü std:: arka plan rengi ile aynı renkte olacak bir anahtar kelimedir. Nasıl uygun görürsen. - Mike DeSimone
Ben düşünmüyorum std:: hiç de zararlı değildir. Çok önemli bilgileri (yani "standart kütüphanenin bir parçası olan her şey") taşıyor ve yine de oldukça kısa ve kompakt bir önek. Çoğu zaman, hiç sorun değil.Bazı kod satırınız var. belirli sembollere başvurmanız gereken yer std ad alanı çok, sonra bir using Bu kapsamdaki açıklama, sorunu güzelce çözer. Ama genel olarak, bu bir gürültü değil, değerli bilgi taşıyor ek olarak belirsizlikleri gidermek için. - jalf
Ne zaman görüyorum std::, Biliyorum ki std:: düşünmek zorunda kalmadan. Görürsem string veya list veya map kendileri, biraz merak ediyorum. - Mateen Ulhaq
@LieRyan O zaman bir şey isimlendirmeden bir geometri kütüphanesi yazmakta iyi şanslar vector, transform veya distance. Ve bunlar sadece örnek birçok çok ortak isim standart kütüphanede kullanılır. C ++ 'nın ayrılmaz bir parçası olan isim-alanı özelliğinin korkudan ya da önyargılı bir bakış açısıyla kullanılmamasını önermek oldukça tersine üreticidir. - Christian Rau


Sanırım derslerin başlık dosyalarına koymak kötü bir şeydir: çünkü o zaman sınıflarınızı kullanmak isteyenleri (başlık dosyalarınızı dahil ederek) 'diğer' kullanma alanlarını da (yani her şeyi görerek) kullanmak için zorlayacaksınız. .

Bununla birlikte, (private) * .cpp dosyalarınıza bir kullanma ifadesi koymakta özgür olabilirsiniz.


Bazı kişilerin, "böyle özgür hisset" dememe katılmamasına dikkat edin - çünkü bir cpp dosyasında bir kullanım ifadesi olmasına rağmen daha iyi bir başlıktan (başlık dosyanızı içeren kişileri etkilemediğinden), bunun hala olmadığını düşünüyorlar iyi (Çünkü koda bağlı olarak, sınıfın uygulanmasını daha zor hale getirebilirdi). Bu SSS konusu diyor,

Kullanım yönergesi, eski C ++ kodu için kullanılabilir ve ad alanlarına geçişi kolaylaştırır, ancak muhtemelen en azından yeni C ++ kodunuzda değil, düzenli olarak kullanmanız gerekir.

İki alternatif önerir:

  • Bir kullanma beyanı:

    using std::cout; // a using-declaration lets you use cout without qualification
    cout << "Values:";
    
  • Üstünden geçin ve sadece std yazın ::

    std::cout << "Values:";
    

309
2017-09-21 03:22



Bir başlıktan daha .cpp dosyasına koymak için daha az kötü, ancak sorun bakım için aynı kalır. Kullandığınız kod / kütüphane / C ++ standardı değiştirildiğinde, aynı ada sahip iki fonksiyonun çakışması riski doğmaktadır. - Étienne
Bunu hiç denedin mi? Çünkü ad alanı yönergesi başka bir dosyaya taşınmayacaktır. (GCC 4.8+) - zackery.fix
@ zackery.fix, "Apple LLVM sürüm 7.0.2 (clang-700.1.81)" yayılır using namespace std; başlığından kaynak dosyasına ve GCC'nin doğrulanmadığını doğruladım. En azından başlıkta "kullanma" yönergesine sahip olmak risklidir. - Franklin Yu
Evet .. LLVM veya clang kullanmıyorum ve bu zaten standart bir yaklaşım değil. - zackery.fix
İnsanlara .cpp dosyasındaki namespace std'yi kullanarak "özgür hissetmelerini" söylememelisiniz. @ Étienne haklı. - einpoklum


Son zamanlarda şikayete girdim Visual Studio 2010. Hemen hemen tüm kaynak dosyalarının şu iki satıra sahip olduğu ortaya çıktı:

using namespace std;
using namespace boost;

Bir çok artırmak özellikleri C ++ 0x standardına giriyor ve Visual Studio 2010'un bir çok C ++ 0x özelliği var, bu yüzden aniden bu programlar derlenmiyordu.

Bu nedenle, kaçınarak using namespace X; Gelecek-provaların bir formudur, kullanımda olan kütüphaneler ve / veya başlık dosyalarındaki değişikliklerin bir programı kırmayacağından emin olmanın bir yoludur.


197
2017-10-28 17:37



Bu. Boost ve std bir var çok Çakışan - özellikle C ++ 11'den beri. - einpoklum
Bunu bir kez yaptım ve bir dersi zor yoldan öğrendim. Şimdi kullanmıyorum using Bir fonksiyon tanımının dışında ve nadiren kullanılır. using namespace hiç - Ferruccio


Kısa versiyon: Başlık dosyalarındaki beyanları veya direktifleri kullanarak global kullanmayın. Uygulama dosyalarında bunları kullanmaktan çekinmeyin. İşte Herb Sutter ve Andrei Alexandrescu'nun bu konu hakkında söyleyecekleri var. C ++ Kodlama Standartları (vurgu için bolding benimdir):

özet

Ad alanı kullanımları size kolaylık sağlamak içindir, başkalarına dayamayacağınız için değil: #include direktifinden önce asla bir kullanım beyanı veya kullanma yönergesi yazmayın.

Corollary: Başlık dosyalarında, yönergeleri kullanarak veya bildirimler kullanarak ad alanı düzeyinde yazma; bunun yerine, açık bir şekilde tüm isimleri nitelendirin. (İkinci kural birinciden gelir, çünkü üstbilgiler #includes'in üstlerinde hangi başlıkların görünebileceğini asla bilemez.)

Tartışma

Kısaca: #include direktiflerinden sonra uygulama dosyalarınızda beyan ve yönergeler kullanarak ad alanını kullanabilir ve bu konuda iyi hissedebilirsiniz. Aksine tekrarlanan iddialara rağmen, beyannameleri ve direktifleri kullanarak ad alanı kötülük değildir ve ad alanlarının amacını bozmazlar. Daha ziyade, ad alanlarını kullanılabilir yapan şeydir.


159
2017-11-03 20:00



Bu aklı başında rehberliğin yanlış yönlendirilmiş cevaplar altında gömülü olması üzücü. - nyholku
Burada sadece bir tane daha programcının görüşü var, ama ben bu ifadeyle% 100 katılıyorum using bir başlıkta asla görünmemeli, ücretsiz lisans hakkında ikna olmuyorum using namespace xyz; kodunuzda, özellikle de xyz olduğu std. ben kullanıyorum using std::vector; form, sadece isim-alanından tek bir unsuru sözde-global kapsam içine çekdiği için, çarpışma riski çok daha azdır. - dgnuff
@ Orbit'teki Işıklar Yarışları elbette sizin fikriniz hakkına sahiptir. Bu cevapta verilen tavsiyelerde bulunmamanız için neden açıklama yapmaya teşebbüs edersek daha yararlı olurdunuz. Özellikle 'kullanmanın' kötü olduğu durumlarda isim alanlarının ne olduğunu anlamak ilginç olurdu? Neden std :: cout yerine std_cout ismini koymuyorsunuz? C ++ / namespace'in yaratıcıları, onları yaratmaktan rahatsız olduklarında bazı fikirlere sahip olmalılar. - nyholku
@nyholku: Gerek yok - diğer cevapların çoğunluğu bende aynı sebepleri veriyor. Ayrıca, yorumuma eklediğim ":)" yi not etmek için lütfen çekinmeyin! Ve bu isim alanlarının kötü olmadığını söylemedim. - Lightness Races in Orbit
Evet, bunu farkettim :) ama IMO'nun cevabının büyük çoğunluğu (bu adaçayla ilgili tavsiyelere karşı) yanlış yönlendiriliyor (şu anda çoğunluğun ne olduğuyla ilgili herhangi bir istatistik yapmamıştım). Ad alanının 'fena değil' olduğunu kabul ederseniz, bu cevaba katılmamanız halinde uygun olduğunu düşündüğünüzü söyleyebilir misiniz? - nyholku


Birincisi, özellikle de başlıklarda, küresel kapsamdaki yönergeleri kullanmamalıdır. Bununla birlikte, bir başlık dosyasında bile uygun olduğu durumlar vardır:

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));
}

Bu açık nitelikten daha iyidir (std::sin, std::cos...) çünkü daha kısa ve kullanıcı tanımlı kayan nokta türleri ile çalışma yeteneğine sahiptir (Argüman Bağımlı Arama yoluyla).


103
2017-09-21 15:47



Üzgünüm, ama buna kesinlikle katılmıyorum. - Billy ONeal
@Billy: Userlib :: cos (userlib :: superint) çağrısını desteklemenin başka yolu yoktur. Her özellik bir kullanımı vardır. - Zan Lynx
@Zan: Tabii ki var. using std::cos; , using std::sinvb. Sorun olsa da iyi tasarlanmış userlib onların olacak sin ve cos kendi ad alanı içinde de, bu gerçekten size yardımcı olmaz. (Bir using namespace userlib bu şablondan önce ve bu kadar kötü using namespace std - ve kapsamı sınırlı değildir.) Ayrıca, bunun gibi gördüğüm tek fonksiyon swapve bu gibi durumlarda sadece şablon uzmanlığı oluşturmanızı öneriyorum std::swap ve tüm problemden kaçınmak. - Billy ONeal
@BillyONeal: template<typename T> void swap(MyContainer<T>&, MyContainer<T>&) (Hiçbir fonksiyon şablonu kısmi uzmanlığı (FTPS) yoktur, bu yüzden bazen aşırı yüklenmeye başvurmanız gerekir. - sbi
@BillyONeal: (7 kere yorum yapıldı!) Yorumunuz yanlış - açıkladığınız durum kesinlikle ADL'nin kapsayacak şekilde tasarlandığını. Kısaca x bir veya daha fazla "ilişkili ad alanı" içerir (ör. namespace userlib) o zaman benzeyen herhangi bir işlev çağrısı cos(x) irade bunlara ek olarak o ad alanlarına bakın - olmadan herhangi using namespace userlib; önceden gerekli. Zan Lynx haklı (ve C ++ isim araması bizans ...) - j_random_hacker


Küresel olarak kullanmayın

Sadece "kötü" olarak kabul edilir dünya çapında kullanılan. Çünkü:

  • Programlamakta olduğunuz ad alanını karıştırıyorsunuz.
  • Okuyucular, bir çok kullandığınızda belirli bir tanımlayıcının nereden geldiğini görmekte zorluk çekecek using namespace xyz.
  • Her ne için doğruysa diğer Kaynak kodunuzun okuyucuları, en sık okuyucusu için daha da doğru: kendiniz. Bir iki yıl sonra gel ve bir bak ...
  • Sadece hakkında konuşuyorsan using namespace std kaptığınız tüm şeylerin farkında olmayabilirsiniz - ve başka bir şey eklediğinizde #include ya da farkında olmadığınız ad çakışmalarını alabileceğiniz yeni bir C ++ revizyonuna geçin.

Yerel olarak kullanabilirsiniz

Devam edin ve yerel olarak (neredeyse) özgürce kullanın. Bu, elbette, sizi tekrar etmenizi engeller. std:: - ve tekrarlama da kötüdür.

Yerel olarak kullanmak için bir deyim

C ++ 03'te, bir uygulama için bir deyim - klişe kodu vardı. swap sınıflarınız için işlev. Aslında bir yerel kullanmanız önerildi using namespace std -- ya da en azından 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(...)`
}

Bu aşağıdaki sihriyi yapar:

  • Derleyici seçecektir std::swap için value_yani void std::swap(int, int).
  • Aşırı yükünüz varsa void swap(Child&, Child&) Derleyici onu seçer uygular.
  • Yaparsan değil derleyicinin kullanacağı aşırı yük var void std::swap(Child&,Child&) ve bunları en iyi şekilde değiştirmeyi deneyin.

C ++ 11 ile artık bu kalıbı kullanmanın bir nedeni yok. Uygulanması std::swap potansiyel bir aşırı yük bulmak için değiştirildi ve onu seçin.


80
2018-01-18 09:34



"Std :: swap uygulaması potansiyel bir aşırı yükleme bulmak için değiştirildi ve onu seçin." - Ne? Bundan emin misin? Bir özel sağlama doğru olsa da swap ilk etapta C ++ 11'de bu kadar önemli değil, std::swap kendisi daha esnektir (hareket anlamını kullanır). Fakat std::swap otomatik olarak kendi özel takasınızı seçerek, bu benim için kesinlikle yeni (ve gerçekten buna inanmıyorum). - Christian Rau
@ChristianRau Ben öyle düşünüyorum, evet. Bunu YERİNDE bir yerde okudum. Biz her zaman sorabiliriz HowardO bilmeli. ben kazma ve kazma Şimdi ... - towi
Swap durumunda bile, daha net (ve şükür daha yaygın olan) deyim yazmaktır using std::swap; ziyade using namespace std;. Daha spesifik bir deyim daha az yan etkiye sahiptir ve bu nedenle kodu daha iyi korunur. - Adrian McCarthy
Son cümle yanlış. C ++ 11'de Std Takas İki Adım resmi olarak kutsanmıştı sağ aramak için yol swapve standarttaki diğer çeşitli yerler dedikleri gibi değiştirildi swap bunun gibi (yukarıda belirtildiği üzere, N.B. using std::swap doğru yol değil using namespace std). Fakat std::swap kendisi kesinlikle değil başka bulmak için değiştirildi swap ve kullan. Eğer std::swap aradı, o zaman std::swap kullanılır. - Jonathan Wakely
Sadece yazmak akıllıca olabilir using std::swap yerel olarak olsa da, yerel ad alanını azaltmak için aynı zamanda kendi kendini belgeleyen kod oluşturma. Nadiren tüm std ad alanıyla ilgileniyorsunuz, bu yüzden ilgilendiğiniz parçaları seçmeniz yeterli. - Lundin


Doğru başlık dosyalarını alırsanız, hex, left, plus veya count küresel kapsamınızda. Farkında değilseniz, bu şaşırtıcı olabilir. std:: bu isimleri içerir. Bu adları yerel olarak kullanmaya da çalışırsanız, bu durum oldukça karışıklığa yol açabilir.

Eğer bütün standartlar kendi isim alanındaysa, kodunuz veya diğer kütüphanelerinizle isim çarpışmaları hakkında endişelenmenize gerek yoktur.


71
2017-09-21 03:23



+ 1 söz değil distance. yine de pratik olarak olanaklı olmayan nitelikli isimleri tercih ederim, çünkü bu benim için okunabilirliği artırıyor. artı, genellikle sözlü konuşmalardaki şeyleri hak etmediğimiz ve olası belirsizlikleri çözme konusunda zaman ayırmaya istekli olduğumuz gerçeğini düşünüyorum, yeterlilik olmadan ne hakkında konuştuğunu anlayabilmenin ve kaynağa başvurmanın değerli olduğu anlamına gelir. Kod, bunun, niteliksiz bile olsa, neyin var olduğunu açık bir şekilde yapılandırdığı anlamına gelir. - Cheers and hth. - Alf
Adil olmak gerekirse, siz dahil değilseniz, bunlardan çoğunuz yok <iomanip>. Yine de iyi bir nokta. - einpoklum