Neden “namespace std kullanılıyor”; kötü uygulama olarak mı değerlendirildi?


2640

Başkaları tarafından using namespace std;kod yazmanın yanlış olduğunu std::coutve std::cinbunun yerine doğrudan kullanmam gerektiğini söyledim .

Neden using namespace std;kötü bir uygulama olarak kabul edilir? Verimsiz mi yoksa belirsiz değişkenler ( stdad alanındaki bir işlevle aynı adı paylaşan değişkenler) bildirme riski var mı? Performansı etkiler mi?


512
Yapabileceğinizi unutmayın: "std :: cout kullanarak;" yani std :: cout yazmanız gerekmez, ancak std ad alanının tamamını aynı anda getirmeyin.
Bill

2
@ ücretli bir nerd google-styleguide.googlecode.com/svn/trunk/… bağlantısı artık çalışmıyor. Görünüşe göre yeni bağlantı google.github.io/styleguide/cppguide.html#Other_C++_Features
MCG

64
Başlık dosyalarında dosya kapsamında 'namespace std kullanımı' kullanmak özellikle kötüdür. Kaynak içeriğinde (* .cpp) tüm içeriklerden sonra dosya kapsamında kullanmak, etkisi tek bir çeviri birimi ile sınırlı olduğu için o kadar da kötü değildir. Daha az problemli olanı, 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-

5
Ben yönergesini kullanarak kullanmak vazgeçirmek ancak belirli ad gibi için istiyorum std::literals::chrono_literals, Poco::Data:Keywords, Poco::Unitsve değişmezleri veya okunabilirliği hileler ele alınacaktır şeyler. Üstbilgi veya uygulama dosyalarındayken. Sanırım bir işlev kapsamında sorun olabilir, ancak değişmez değerler ve şeyler dışında, bu yararlı değildir.
Ludovic Zenohate Lagouardette

7
@Jon: Özellikle ad alanı std ile ilgisi yok. Vurgu, "üstbilgi dosyalarındaki dosya kapsamına" yönelikti. Bir öneri olarak: Başlık dosyalarındaki dosya kapsamında "ad alanı kullanma" (std veya diğer) kullanmayın. Uygulama dosyalarında kullanmakta sorun yoktur. Belirsizlik için özür dilerim.
sh-

Yanıtlar:


2230

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

using namespace foo;
using namespace bar;

Her şey iyi çalışıyor ve Blah()Foo'dan ve Quux()Bar'dan sorunsuz arayabilirsiniz . Ancak bir gün Foo 2.0'ın yeni bir sürümüne geçtiniz, bu da şimdi adlı bir işlev sunuyor Quux(). Artık bir çatışmanız var: Hem Foo 2.0 hem de Bar Quux()küresel ad alanınıza aktarılıyor. Bu, özellikle fonksiyon parametreleri eşleşirse, düzeltmek için biraz çaba harcayacaktır.

Kullanmış olsaydınız foo::Blah()ve bar::Quux()o zaman tanıtımı foo::Quux()bir olay olmazdı.


435
Ben her zaman Python'ın "bhn olarak ithal big_honkin_name" sevdim, böylece sadece "big_honkin_name.something" yerine "bhn.something" kullanabilirsiniz - gerçekten yazmayı keser. C ++ 'da böyle bir şey var mı?
paxdiablo

764
@Pax ad alanı io = boost :: dosya sistemi;
AraK

152
Bence "düzeltmek için biraz çaba" olduğunu söylemek abartılı şeyler. Yeni foo :: Quux örneğiniz olmayacak, bu yüzden bar :: Quux ile mevcut tüm kullanımlarınızı netleştirin.
MattyT

289
Mantıklı herhangi bir kişi, niteliksiz adı std türleriyle çakışan türlerle bir kütüphane yaratır mı?
erikkallen

94
@TomA: Sorun, #definekendisini ad alanlarıyla sınırlamaması, ancak tüm kod tabanı üzerinde ezilmesidir . İstediğiniz ad alanı takma adıdır.
sbi

1391

Greg'in yazdığı her şeye katılıyorum , ama eklemek istiyorum: Greg'in söylediğinden daha da kötüleşebilir!

Library Foo 2.0 bir işlev Quux()sunabilir, bu da bazı çağrılarınız için yıllarca kodunuzdan Quux()çok daha iyi bir eşleşme bar::Quux(). Sonra kodunuz hala derlenir , ancak sessizce yanlış işlevi çağırır ve tanrı-ne bilir. Bu her şeyin alabileceği kadar kötü.

Unutmayın stdad bunların çoğu tanımlayıcıları, tonlarca vardır çok yaygın olanları (düşünmek list, sort, string, iteratorçok başka bir kod görünmesini çok muhtemeldir, vs.).

Beklenmeyen bu düşünün: Orada bir soru sordu hemen hemen tam olarak bu (nedeniyle ihmal denilen yanlış işlevi meydana geldiği Yığın taşması burada std::ben bu cevabı verdikten sonra yarım yaklaşık bir yıl önek). İşte böyle bir sorunun daha yeni bir örneği. Yani bu gerçek bir problem.


İşte bir veri noktası daha: Birçok yıl önce, standart kütüphaneden her şeyin ön ekini almak zorunda kaldığımı sinir bozucu buldum std:: . Daha sonra başlangıçta usingfonksiyon kapsamları dışında hem direktiflerin hem de bildirimlerin yasaklanmasına karar verildiği bir projede çalıştım . Bil bakalım ne oldu? Ön eki yazmaya alışmamızın çoğunu birkaç haftamız aldı ve birkaç hafta sonra çoğumuz kodun daha okunaklı olduğunu kabul etti . Bunun bir nedeni var: Kısa veya uzun düzyazıdan hoşlanmanızın öznel olması, ancak öneklerin koda objektif olarak netlik katması. Sadece derleyici değil, siz de hangi tanımlayıcıya atıfta bulunduğunu görmeyi daha kolay buluyorsunuz.

On yıl içinde, bu proje birkaç milyon kod satırına sahip oldu. Bu tartışmalar tekrar tekrar gündeme geldiğinden, bir zamanlar (izin verilen) fonksiyon kapsamının usingprojede ne sıklıkta kullanıldığını merak ettim . Bunun için kaynakları gittim ve sadece bir veya iki düzine yer buldum. Bana göre bu, geliştiriciler std::denendikten sonra, kullanılmasına izin verilen yerlerde bile her 100 kLoC'de bir kez bile direktifleri kullanmak için yeterince acı bulamadıklarını gösterir.


Alt satır: Her şeyin açıkça ön ekinin zararı yoktur, alışmak çok az zaman alır ve nesnel avantajları vardır. Özellikle, kodun derleyici ve insan okuyucular tarafından yorumlanmasını kolaylaştırır - ve muhtemelen kod yazarken ana amaç bu olmalıdır.


140
Tek bir satıra paketleyebileceğiniz kodun yoğunluğuna önemli ölçüde zarar verir. Sonunda kodunuzu çok uzun soluklu bir şekilde yazıyorsunuz; okunabilirliği azaltır. Şahsen, daha kısa (ama çok kısa değil) kod daha okunabilir olma eğiliminde olduğunu düşünüyorum (çünkü okumak için daha az şey ve hakkında daha az şey dikkatini dağıtmak için).
Yalan Ryan

91
Sanırım eski günlerde C ++ standart bir stringsınıfa sahip değildi ve görünüşe göre her kütüphane kendine aitti. Ne söyleyelim: Kodumuzu yazmaya devam edeceğiz std::ve grep -v std:: | vimkodumuza göz atarken de çalıştırabilirsiniz. Veya editörünüze std::, arka plan rengiyle aynı renkte olacak bir anahtar kelime olduğunu öğretebilirsiniz . Nasıl uygun görürsen.
Mike DeSimone

79
Hiç std::zararlı olduğunu düşünmüyorum . Çok önemli bilgiler taşır (yani "sonra gelen her şey standart kütüphanenin bir parçasıdır" ve hala oldukça kısa ve kompakt bir önektir. Çoğu zaman sorun olmaz. Bazen birkaç satır kodunuz vardır stdad alanındaki belirli simgelere çok fazla başvurmanız gerekiyor ve daha sonra usingbu kapsamdaki bir ifade sorunu güzelce çözüyor.Ancak genel olarak, gürültü değil, belirsizlikleri kaldırmanın yanı sıra değerli bilgiler de iletiyor .
jalf

146
Ne zaman görsem std::, std::bunun hakkında düşünmek zorunda kalmadan olacağını biliyorum. Eğer görürsem stringya listda mapkendi kendime, biraz merak ediyorum.
Mateen Ulhaq

67
@LieRyan Sonra hiç bir şey adlandırma olmadan geometri kütüphane yazmak iyi şanslar vector, transformya distance. Ve bunlar sadece standart kütüphanede kullanılan pek çok yaygın isme örnektir . Onları korkudan veya C + + 'nın ayrılmaz bir parçası olan ad alanı özelliğinin önyargılı bir görüşünden kullanmamanızı önermek oldukça zıttır.
Christian Rau

420

Koymak sorunu using namespaceSınıflarınızın başlık dosyalarını , sınıflarınızı kullanmak isteyen herkesi (başlık dosyalarınızı dahil ederek) bu diğer ad alanlarını 'kullanması' (yani her şeyi görmesi) için zorlamasıdır.

Ancak, (private) * .cpp dosyalarınıza using ifadesi koymaktan çekinmeyin.


Bazı insanların böyle "özgür hissetme" dememe katılmamalarına dikkat edin - çünkü usingbir cpp dosyasındaki bir ifade bir başlıktan daha iyi olsa da (başlık dosyanızı içeren kişileri etkilemediğinden), yine de olmadığını düşünüyorlar. iyi (koda bağlı olarak sınıfın uygulanmasının sürdürülmesini zorlaştırabilir). Bu C ++ Süper SSS girişi diyor ki,

Using-yönergesi eski C ++ kodu ve ad alanlarına geçişi kolaylaştırmak için vardır, ancak muhtemelen en azından yeni C ++ kodunuzda düzenli olarak kullanmamalısınız.

SSS iki alternatif öneriyor:

  • Kullanım beyanı:

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

    std::cout << "Values:";

1
Tabii ki, küresel cout durumunu da asla varsaymamalısınız, birisinin std: cout << std :: hex olduğu ve daha sonra std :: restore_cout_state yapamadığı sürece. Ama bu tamamen başka bir fatberg.
Móż

233

Kısa bir süre önce Visual Studio 2010 hakkında bir şikayetle karşılaştım . Kaynak dosyaların neredeyse hepsinin şu iki satıra sahip olduğu ortaya çıktı:

using namespace std;
using namespace boost;

Birçok Boost özelliği 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çınmak using namespace X;gelecekteki bir kanıtlama biçimidir, kullanılan kitaplıklarda ve / veya başlık dosyalarında yapılan bir değişikliğin bir programı bozmayacağından emin olmanın bir yolu.


14
Bu. Boost ve std çok fazla örtüşmeye sahip - özellikle C ++ 11'den beri.
einpoklum

1
Bunu bir kez yaptım ve zor yoldan bir ders aldım. Şimdi hiçbir zaman usingbir fonksiyon tanımının dışında kullanmıyorum ve nadiren kullanıyorum using namespace.
Ferruccio

210

Kısa sürüm: usingbaşlık dosyalarında genel bildirimler veya yönergeler kullanmayın . Bunları uygulama dosyalarında kullanmaktan çekinmeyin. İşte ne Herb Sutter ve Andrei Alexandrescu bu konuda söylemek zorunda Standartları Kodlama C ++ (vurgu için kalınlaştırmak benimdir):

özet

Ad alanı kullanımı size kolaylık sağlamak içindir, başkalarına vermeniz için değildir: #include yönergesinden önce asla bir kullanım bildirimi veya kullanım talimatı yazmayın.

Sonuç: Başlık dosyalarında, yönergeler veya bildirimler kullanarak ad alanı düzeyinde yazmayın; bunun yerine, tüm adları açıkça ad-alanı ile nitelendirin. (İkinci kural birinciden sonra gelir, çünkü başlıklar #includes'in başka hangi başlıklardan sonra görünebileceğini asla bilemez.)

Tartışma

Kısaca: #include yönergelerinden sonra ve uygulama hakkında iyi hissettikten sonra uygulama dosyalarınızda bildirimleri ve yönergeleri kullanarak ad alanını kullanabilirsiniz ve kullanmalısınız. Aksine ileri sürülen iddialara rağmen, bildirimleri ve direktifleri kullanan ad alanı kötü değildir ve ad alanlarının amacını bozmazlar. Bunun yerine, ad alanlarını kullanılabilir yapan şeydir .


4
Burada sadece bir programcının görüşü daha var, ancak% 100 kelimesinin usinghiçbir zaman bir başlıkta görünmemesi gerektiğini kabul ederken using namespace xyz;, kodunuzda herhangi bir yere yerleştirmek için ücretsiz lisans konusunda ikna olmadım , özellikle xyzde std. Kullandığım using std::vector;tek dolayısıyla bir çarpışma çok daha az riskine sebep sözde küresel etki alanına dahil ad tek bir öğesini çeker beri formunu.
dgnuff

2
@ Orbit'teki @Lightness Races, elbette sizin görüşünüze hakkınız var. Neden bu cevapta verilen tavsiyeyi kabul etmediğiniz konusunda bazı girişimlerde bulunmuş olsaydınız daha yararlı olurdu. Özellikle onları kullanmak 'kötü' ise ad alanlarının ne anlama geldiğini anlamak ilginç olurdu? Neden sadece std :: cout yerine şeyleri std_cout olarak adlandırmıyorsunuz ... C ++ / ad alanının yaratıcıları onları oluşturmak için uğraştıklarında bazı fikirleri olmalı.
nyholku

1
@nyholku: Gerek yok - diğer cevapların çoğu benimle aynı nedenleri veriyor. Ayrıca benim yorum ekledi ":)" not için hiç tereddüt etmeyin! Ve isim alanlarının kötü olduğunu söylemedim.
Yörüngedeki Hafiflik Yarışları

Evet, fark ettim :) ama IMO (bu bilge tavsiyeye aykırı olan) cevabın çoğunluğu yanlış yönlendiriliyor (şu anda çoğunluğun ne olduğunu herhangi bir istatistik yapmadım). Ad alanının 'kötü olmadığını' kabul ediyorsanız, bu yanıta katılmıyorsanız uygun olduğunu düşündüğünüzü söyleyebilir misiniz?
nyholku

Yardım edemem ama using namespacekötülüğün kötülük gibi gotoolduğunu hissediyorum . Her ikisinin de geçerli kullanımları vardır, ancak 1000'in 999 katı yanlış kullanılır. Yani, evet, using namespacekaynakta diğer içeriklerin ad alanlarını kirletmeyeceksiniz, temiz. Ama yine de sizi ( + örtülü Foo: :) aradığınız ve aniden kod kırma (ilgili değişiklikler olmadan) nedeniyle ortaya çıkan "eğlenceye" karşı korumaz çünkü sadece bir yere eklenmiş, çünkü daha iyi olur maç (ve şimdi bunun yerine çağrılır)using namespace Foousing namespace Barbaz(xyz)Bar::baz()
CharonX

122

Bir kullanmamalısınız usingözellikle başlıklarında, küresel kapsamda yönergeyi. Ancak, 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 kalifikasyondan ( std::sin, std::cos...) daha iyidir , çünkü daha kısadır ve kullanıcı tanımlı kayan nokta türleriyle ( bağımsız değişkene bağlı arama (ADL) aracılığıyla) çalışma yeteneğine sahiptir .


9
Üzgünüm, ama buna kesinlikle katılmıyorum.
Billy ONeal

4
@Billy: userlib :: cos (userlib :: superint) çağrısını desteklemenin başka bir yolu yoktur. Her özelliğin bir kullanımı vardır.
Zan Lynx

17
@Zan: Tabii ki var. using std::cos;, using std::sinVb konu olsa iyi tasarlanmış herhangi olmasıdır userlibonların sahip oluyor sinve cosbu gerçekten yardımcı olmuyor bu yüzden, hem de kendi ad alanının içinde. ( using namespace userlibBu şablondan önce bir tane olmadığı ve bu kadar da kötü olmadığı sürece using namespace std- ve kapsam sınırlı değildir.) Ayrıca, bunun gördüğüm tek işlev olduğunu swapve bu gibi durumlarda sadece bir şablon oluşturmanızı tavsiye ederim. std::swaptüm sorunun uzmanlaşması ve önlenmesi.
Billy ONeal

11
@BillyONeal: template<typename T> void swap(MyContainer<T>&, MyContainer<T>&)(Fonksiyon şablonu kısmi uzmanlığı (FTPS) yoktur, bu yüzden bazen bunun yerine aşırı yüklemeye başvurmanız gerekir.
sbi

38
@BillyONeal: (7 kez oy verildi!) Yorumunuz yanlış - açıkladığınız durum tam olarak ADL'nin kapsaması için tasarlandı. Kısaca, eğer xsahip bir veya daha fazla "ilişkili ad" (örneğin o tanımlanmış ise namespace userlib) görünüyor gibi o sonra herhangi bir işlev çağrısı cos(x)olacaktır ayrıca bu ad bakmak - olmadan herhangi using namespace userlib;gerekli olan önceden. Zan Lynx haklı (ve C ++ isim araması bizans ...)
j_random_hacker

97

Küresel olarak kullanmayın

Sadece küresel olarak kullanıldığında "kötü" olarak kabul edilir . Çünkü:

  • Programladığınız ad alanını karıştırıyorsunuz.
  • Okuyucular, birçoğunu kullandığınızda belirli bir tanımlayıcının nereden geldiğini görmekte zorluk çekecektir using namespace xyz.
  • Kaynak kodunuzun diğer okuyucuları için geçerli olan her şey , en sık okunan okuyucuları için daha da doğrudur: kendiniz. Bir iki yıl sonra geri dönün ve bir göz atın ...
  • Sadece hakkında konuşursanız using namespace std, yakaladığınız tüm şeylerin farkında olmayabilirsiniz - ve başka bir tane eklediğinizde #includeveya yeni bir C ++ revizyonuna geçtiğinizde , farkında olmadığınız isim çakışmaları alabilirsiniz.

Yerel olarak kullanabilirsiniz

Devam edin ve yerel olarak (neredeyse) özgürce kullanın. Bu, elbette, tekrarlanmanızı önlerstd:: - ve tekrarlama da kötüdür.

Yerel olarak kullanmak için bir deyim

C ++ 03'te swapsınıflarınız için bir işlev uygulamak için bir deyim - kaynak kodu - vardı . Aslında yerel bir using namespace std- veya 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 şu büyüyü yapar:

  • Derleyici seçecektir std::swapFOR value_yanivoid std::swap(int, int) .
  • Aşırı yükünüz varsa void swap(Child&, Child&)Uygulanan derleyici onu seçecektir.
  • Eğer yoksa değil o aşırı yüklenme derleyici kullanır void std::swap(Child&,Child&)ve bu takas elinden geleni.

C ++ 11 ile artık bu kalıbı kullanmak için hiçbir neden yoktur. Uygulanması, std::swappotansiyel bir aşırı yük bulmak ve seçmek için değiştirildi.


5
"Std :: swap uygulaması potansiyel bir aşırı yük bulmak ve onu seçmek için değiştirildi." - Ne? Bundan emin misin? Her ne kadar swapilk olarak bir gelenek sağlamanın C ++ 11'de o kadar önemli olmadığı doğru olsa da, std::swapkendisi daha esnek olduğundan (hareket semantiği kullanır). Ama std::swapotomatik olarak kendi özel takasınızı seçmek, bu benim için kesinlikle yeni (ve gerçekten inanmıyorum).
Christian Rau

@ChristianRau Sanırım evet. Bunu SO'da bir yerde okudum. Howard'a her zaman sorabiliriz , bilmeli. Ben am kazma ve kazma ... şimdi
towi

14
Takas durumunda bile, daha açık (ve neyse ki daha yaygın) deyim yazmaktan using std::swap;ziyade yazmaktır using namespace std;. Daha spesifik deyim daha az yan etkiye sahiptir ve bu nedenle kodu daha sürdürülebilir hale getirir.
Adrian McCarthy

11
Son cümle yanlış. C ++ 11'de Std Swap İki Adımı resmi olarak aramanın doğru yolu olarak kutsanmıştı swapve standarttaki diğer çeşitli yerler, swapböyle çağırdıklarını söylemek için değiştirildi (yukarıda belirtildiği gibi, NB using std::swapdoğru yoldur, değil using namespace std). Ama std::swapkendisi ısrarla oldu değil diğer bazı bulmak için değişti swapve kullanmak. Eğer std::swapçağrılırsa, o std::swapzaman kullanılır.
Jonathan Wakely

3
Ancak using std::swapyerel olarak yazmak, yerel ad alanını azaltmak ve aynı zamanda kendi kendini belgelendirme kodu oluşturmak akıllıca olabilir . Nadiren tüm std ad alanı ile ilgileniyorsunuz, bu yüzden sadece ilgilendiğiniz parçaları seçin.
Lundin

79

Doğru başlık dosyalarını içe Eğer aniden gibi isimler var hex, left, plusya countda küresel kapsamda. Bu std::adları içerdiğinin farkında değilseniz, bu şaşırtıcı olabilir . Bu adları yerel olarak da kullanmaya çalışırsanız, bu biraz karışıklığa neden olabilir.

Tüm standart şeyler kendi ad alanındaysa, kodunuzla veya diğer kütüphanelerle ad çakışmaları konusunda endişelenmenize gerek yoktur.


12
Bahsetmemek için +1 distance. hala mümkün olan her yerde kalifiye olmayan isimleri tercih ediyorum, çünkü bu benim için okunabilirliği arttırıyor. artı, genellikle sözlü konuşmada bir şeyleri nitelemediğimizi ve olası belirsizlikleri çözmek için zaman harcamak istediğimizi düşünüyorum, bunun nitelikler olmadan ne hakkında konuştuğunu anlamanın ve kaynağa başvurmanın değeri olduğu anlamına gelir. kod, niteliksiz olsa bile neyle ilgili olduğu açık bir şekilde yapılandırıldığı anlamına gelir.
Şerefe ve s. - Alf

Adil olmak gerekirse, dahil etmiyorsanız bunların çoğuna sahip değilsiniz <iomanip>. Yine de, iyi bir nokta.
einpoklum

48

Başka bir sebep de sürpriz.

Ben görürseniz cout << blah, yerine std::cout << blahI. düşünüyorum: Bu nedir cout? Normal coutmi? Özel bir şey mi?


25
Bu bir şaka mı? Gerçekten söyleyemem. Eğer o zaman ben şahsen normal bir "cout" varsayalım çünkü aksi takdirde bir BEYOND BÜYÜK kod kokusu, IMO olacaktır kod güvenmiyorum varsayalım. ... Ve koda güvenmiyorsan neden ilk etapta kullanıyorsun? "HER ŞEYE GÜVEN !!" demediğimi unutmayın. ancak, GitHub'dan iyi bilinen bir kütüphane veya başka bir şeyle uğraşıyorsanız, bu biraz uzak görünüyor.
Brent Rittenhouse

28
@BrentRittenhouse coutkötü bir örnektir çünkü herkes bunu tanır. Ama futurefinansal bir uygulamada hayal edin . Belirli bir tarihte bir şey almak veya satmak bir sözleşme midir? Hayır değil. Eğer kod std::futuresöylediyse bu kadar kolay karıştırılmazsınız.
James Hollis

2
@BrentRittenhouse belki biraz kötü bir örnek, cout'a sahip en az dört farklı kütüphane var. "Standart kütüphane? Libstdc ++? Stl? Başka bir şey mi?" Olabilir. Ve hayır, herkes bilmiyor std :: cout, en azından doğal olarak, aldığımız 7 yeni işçiden 6'sı bilmiyor. Çünkü eğitim müfredatı eğitimde kullanılmaz. Printfs'i kovalamam lazım. Veya hata ayıklama () - Qt.
Swift - Cuma Pastası

1
Gerçekten mi? Soo'nun ilk bölümünün ilk örneğinde C ++ ile ilgili birçok kitap var, eğer yeni bir cismin bildiği tek C ++ ise (ekleme operatörü kullanımı ile) .
mckenzm

@mckenzm Karmaşıklığı azaltmak için bir kitap veya ders notlarına koyabilirim, ancak kodda değil
Martin Beckett

45

Deneyimli programcılar, sorunlarını çözen her şeyi kullanırlar ve yeni sorunlar yaratan her şeyden kaçınırlar ve bu nedenden dolayı başlık dosyası düzeyinde kullanma yönergelerinden kaçınırlar.

Deneyimli programcılar ayrıca kaynak dosyalarında tam ad nitelendirmesinden kaçınmaya çalışırlar. Bunun küçük bir nedeni , iyi nedenler olmadıkça daha az kod yeterli olduğunda daha fazla kod yazmanın zarif olmamasıdır . Bunun en büyük nedeni, bağımsız değişkene bağlı aramayı (ADL) kapatmaktır.

Bu iyi nedenler nelerdir? Bazen programcılar açıkça ADL'yi kapatmak isterler, bazen de belirsizleştirmek isterler.

Yani aşağıdakiler uygundur:

  1. İşlev düzeyinde kullanım yönergeleri ve işlevlerin uygulamaları içindeki kullanım bildirimleri
  2. Kaynak dosya içindeki kaynak dosya düzeyinde kullanma bildirimleri
  3. (Bazen) kaynak dosya düzeyinde using-yönergeleri

43

Küresel olarak kullanılmaması gerektiğine katılıyorum, ancak a namespace. "C ++ Programlama Dili" nden bir örnek :

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

}

Bu örnekte, kompozisyonlarından kaynaklanan potansiyel isim çatışmaları ve belirsizlikleri çözdük.

Orada açıkça bildirilen adlar (gibi-beyanları kullanılarak bildirilen adlar dahil His_lib::String) bir using-yönergesi ( using namespace Her_lib) ile başka bir kapsamda erişilebilir hale getirilen adlara göre önceliklidir .


29

Ben de bunun kötü bir uygulama olduğunu düşünüyorum. Neden? Sadece bir gün, bir isim alanının işlevinin bir şeyleri bölmek olduğunu düşündüm, bu yüzden her şeyi tek bir küresel torbaya atmakla bozmamalıydım.

Ancak, sık sık 'cout' ve 'cin' kullanırsam, using std::cout; using std::cin;.cpp dosyasına (yayıldıkça asla başlık dosyasında #include) yazmam gerekir . Ben kimsenin aklı başında hiç bir akış isim olacağını düşünüyorum coutya cin. ;)


7
Bu bir yerel kullanım bildirimi , bir kullanım direktifinden çok farklı bir şey .
sbi

25

Kodu görmek ve ne yaptığını bilmek güzel. Ben görürsem std::coutbunu biliyorum coutakışı stdkütüphanesine. Eğer görürsem coutbilmiyorum. Bu olabilir olmak coutakışı stdkütüphanesine. Ya int cout = 0;da aynı işlevde on satır daha yüksek olabilir . Veya bu dosyada staticadlandırılmış bir değişken cout. Herhangi bir şey olabilir.

Şimdi, özellikle büyük olmayan bir milyon satır kod tabanı alın ve bir hata arıyorsunuz, yani bu bir milyon satırda yapması gerekeni yapmayan bir satır olduğunu biliyorsunuz. cout << 1;bir static intismi okuyabilir cout, bir bit sola kaydırabilir ve sonucu atabilir. Bir hata mı arıyorsunuz, bunu kontrol etmem gerekecekti. Gerçekten nasıl görmeyi tercih ettiğimi görebiliyor std::coutmusunuz?

Eğer bir öğretmenseniz ve yaşamak için herhangi bir kod yazmak ve korumak zorunda değilseniz, bu gerçekten iyi bir fikir gibi görünen şeylerden biridir. Kod görmeyi seviyorum nerede (1) ne yaptığını biliyorum; ve (2) Yazan kişinin ne yaptığını bildiğinden eminim.


4
"Std :: cout << 1", std ad alanında tek bir kaydırma yaparak ve sonucu atmadan cout adlı statik bir int okumuyor biliyor musunuz? Ayrıca "<<" ne yapar biliyor musunuz;) ??? ... bu cevap 'kullanmaktan' kaçınmak için iyi bir veri noktası gibi görünmüyor.
nyholku

4
Birisi std :: cout'u bir tamsayı olarak yeniden tanımladıysa, probleminiz teknik değil, sosyal - birisi sizin için var. (ve muhtemelen #define true false, vb. gibi tüm başlıkları da kontrol etmelisiniz)
Jeremy Friesner

2
Ben cout gördüğümde biliyorum std :: cout, her zaman. Eğer yanılıyorsam, bu kodu yazan kişi değil, ben değil :)
Tien Do

22

Her şey karmaşıklığı yönetmekle ilgilidir. Ad alanını kullanmak istemediğiniz şeyleri çeker ve böylece hata ayıklamayı zorlaştırır (muhtemelen diyorum). Her yerde std :: 'yi kullanmak daha zordur (daha fazla metin ve hepsi).

Kurslar için atlar - karmaşıklığınızı en iyi nasıl yapabildiğinizi ve hissedebildiğinizi yönetin.


18

Düşünmek

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


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

class stringstream {  // Uh oh
};

Bunun basit bir örnek olduğunu unutmayın. 20 içerik ve diğer içe aktarma dosyalarınız varsa, sorunu çözmek için bir ton bağımlılığa sahip olacaksınız. Bununla ilgili en kötü şey, çakışan tanımlara bağlı olarak diğer modüllerde ilgisiz hatalar alabilmenizdir.

Korkunç değil, ancak başlık dosyalarında veya genel ad alanında kullanmadan baş ağrısını kurtaracaksın. Muhtemelen çok sınırlı kapsamlarda bunu yapmak iyidir, ancak işlevlerimin nereden geldiğini açıklığa kavuşturmak için fazladan beş karakteri yazarken hiç sorun yaşamadım.


18
  1. Sizden farklı stil ve en iyi uygulama görüşlerine sahip kişiler tarafından yazılan kodu okuyabilmeniz gerekir.

  2. Sadece kullanıyorsanız cout, kimse karışmaz. Ancak etrafta uçan çok sayıda ad alanınız olduğunda ve bu sınıfı gördüğünüzde ve tam olarak ne yaptığından emin değilseniz, ad alanının açık olması, bir tür yorum olarak hareket eder. İlk bakışta "ah, bu bir dosya sistemi işlemi" veya "ağ işi yapan" ifadesini görebilirsiniz.


17

Aynı anda çok sayıda ad alanı kullanmak afet için bir reçetedir, ancak SADECE ad alanını stdve yalnızca ad alanını kullanmaktır.std bence bir anlaşma o kadar büyük değil çünkü yeniden tanımlama sadece kendi kodunuzla gerçekleşebilir ...

Bu yüzden sadece "int" veya "class" gibi ayrılmış isimler olarak işlevlerini düşünün ve hepsi bu.

İnsanlar bu konuda anal olmayı bırakmalı. Öğretmeniniz baştan beri haklıydı. Sadece ONE ad alanını kullanın; ilk etapta ad alanlarını kullanmanın bütün mesele budur. Aynı anda birden fazla kullanmamanız gerekir. Siz kendiniz değilse. Yani tekrar, yeniden tanımlama olmayacak.


Kısa dizeleri gibi - çarpışmalar oluşturmak zor değil mi min, endve lessgörünür std::ad. Ama dahası, std::içinde binlerce sembol var, okuyucunun bilmedikleri yeni bir sembolün nereden geldiğini bilmesi faydalı.
Tom Swirly

Std ad alanı vardır, çünkü siz, meslektaşlarınız veya kullandığınız ara katman yazılımı yazan kişiler, adları ad alanlarının içine koymak konusunda her zaman akıllı değildirler. Böylece, std :: min ve başka hiçbir şeyi içe aktarabilirsiniz, diyelim ki std :: min ve bir başkasının mirası :: min () arasında std'deki zamandan önceki bir çarpışmayı başlatırsınız.
Aiken Drum

14

Buradaki diğerleriyle aynı fikirdeyim, ancak okunabilirlikle ilgili endişeleri ele almak istiyorum - sadece dosyanızın, fonksiyonunuzun veya sınıf bildiriminizin en üstündeki typedef'leri kullanarak bunlardan kaçınabilirsiniz.

Genellikle sınıf bildirimimde, bir sınıftaki yöntemler benzer veri türleri (üyeler) ile ilgilenme eğilimi gösterdiğinden ve typedef sınıf bağlamında anlamlı bir ad atamak için bir fırsattır. Bu aslında sınıf yöntemlerinin tanımlarında okunabilirliğe yardımcı olur.

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

ve uygulamada:

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

aksine:

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

veya:

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

Sadece küçük bir yorum, typedef yararlı olsa da typedef kullanmak yerine Lines temsil eden bir sınıf yapmak düşünecektim.
Eyal Solnik

14

Endişeyi açıklığa kavuşturmak için somut bir örnek. İki kütüphaneniz olduğu foove barher birinin kendi ad alanı olan bir durumunuz olduğunu düşünün :

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

namespace bar {
    ...
}

Şimdi kullandığınız diyelim foove baraşağıdaki gibi kendi programında birlikte:

using namespace foo;
using namespace bar;

void main() {
    a(42);
}

Bu noktada her şey yolunda. Programınızı çalıştırdığınızda 'Bir şey yapar'. Ama daha sonra güncellersiniz barve diyelim ki değişti:

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

Bu noktada bir derleyici hatası alırsınız:

using namespace foo;
using namespace bar;

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

Bu yüzden 'a' nın ne anlama geldiğini açıklığa kavuşturmak için biraz bakım yapmanız gerekir foo::a. Bu istenmeyen bir durumdur, ancak neyse ki oldukça kolaydır (sadece foo::tüm çağrıların önüne ekleyina derleyicinin belirsiz olarak işaretlediği ).

Ancak bunun yerine çubuğun bunun gibi görünmesi için değiştiği alternatif bir senaryo düşünün:

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

Bu noktada a(42)aniden bağlanmak bar::ayerine foo::a'bir şey' yapmak yerine 'tamamen farklı bir şey' yapar. Derleyici uyarısı falan yok. Programınız sessizce öncekinden farklı bir şey yapmaya başlar.

Bir ad alanı kullandığınızda böyle bir senaryoyu riske atıyorsunuz, bu yüzden insanlar ad alanlarını kullanmaktan rahatsız oluyorlar. Bir ad alanında ne kadar çok şey olursa, çakışma riski o kadar artar, bu nedenle insanlar stddiğer ad alanlarına göre ad alanını kullanmaktan (bu ad alanındaki şeylerin sayısı nedeniyle) daha da rahatsız olabilirler .

Sonuçta bu, yazılabilirlik ile güvenilirlik / sürdürülebilirlik arasında bir değiş tokuştur. Okunabilirlik de faktör olabilir, ancak bununla ilgili argümanları her iki şekilde de görebiliyordum. Normalde güvenilirlik ve sürdürülebilirliğin daha önemli olduğunu söyleyebilirim, ancak bu durumda oldukça nadir bir güvenilirlik / sürdürülebilirlik etkisi için yazılabilirlik maliyetini sürekli ödersiniz. 'En iyi' değiş tokuş, projenize ve önceliklerinize göre belirlenir.


İkinci senaryo benim için anlaşmayı zorluyor. Yine ad alanı yok. Bu tür küçük değişiklikler, kaputun altında tespit edilemez.
safe_malloc

13

Ad alanı adlandırılmış bir kapsamdır. Ad alanları, ilgili bildirimleri gruplandırmak ve ayrı öğeleri ayrı tutmak için kullanılır. Örneğin, ayrı ayrı geliştirilen iki kitaplık, farklı öğelere başvurmak için aynı adı kullanabilir, ancak kullanıcı yine de her ikisini de kullanabilir:

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
    // ...
}

Bir ad alanı adını tekrarlamak hem okuyucular hem de yazarlar için dikkat dağıtıcı olabilir. Sonuç olarak, belirli bir isim alanındaki isimlerin açık bir nitelik olmadan kullanılabilir olduğunu söylemek mümkündür. Örneğin:

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
    // ...
}

Ad alanları, farklı kitaplıkların ve farklı kod sürümlerinin yönetimi için güçlü bir araç sağlar. Özellikle, programcıya yerel olmayan bir isme ne kadar açık bir referans yapılacağına dair alternatifler sunarlar.

Kaynak: Bjarne Stroustrup'un C ++ Programlama Diline Genel Bakış


4
Bjarne Stroustrup'un -2 ... kazanmış olduğu hiç kimsenin rehberliğine dayanmayan bu cevap çok ilginçti ... oğlan Bjarne, C ++
nyholku

@nyholku: Bkz bu .
sbi

10

using namespace stdAlgoritma kütüphanesinde de işlev olan sayım belirsizliğinden dolayı derleme hatası veren bir örnek .

#include <iostream>

using namespace std;

int count = 1;
int main() {
    cout << count << endl;
}

2
::count--sorun çözüldü. Genellikle std ad alanlarından başka yerlere göre daha fazla öğeye sahip olursunuz, ergo ad alanı yönergesini kullanmak yazmayı kurtarabilir.
PSkocik

Buradaki asıl sorun, C ++ 'ın hala isimsiz globaller olmasıdır. Bu ve 'bu' yöntemlerde örtük olması, o kadar çok hataya ve soruna neden olur, hatta doğru 'sayım' değişkeni ile bile onları sayamam. ;)
Aiken Davul

9

Yazılımınızı veya proje performansınızı daha da kötüleştirmez. Kaynak kodunuzun başına ad alanının eklenmesi kötü değildir. Dahilusing namespace stdTalimatın ihtiyaçlarınıza ve yazılımı veya projeyi geliştirme şeklinize göre değişir.

namespace stdC ++ standart fonksiyonları ve değişken içerir. Bu ad alanı, genellikle C ++ standart işlevlerini kullanırken yararlıdır.

Bu sayfada belirtildiği gibi :

İsim alanı std kullanan ifade genellikle kötü uygulama olarak kabul edilir. Bu ifadenin alternatifi, her tür bildirdiğimizde, kapsam operatörünü (: :) kullanarak tanımlayıcının ait olduğu ad alanını belirtmektir.

Ve bu düşünceye bakın :

Ad alanını yoğun bir şekilde kullandığınızda ve hiçbir şeyin çarpışmayacağından emin olduğunuzda, kaynak dosyanızda "namespace std kullanımı" kullanmakla ilgili bir sorun yoktur.

Bazı insanlar bunun using namespace stdkaynak dosyalarınıza eklemek için kötü bir uygulama olduğunu söylemişti, çünkü bu ad alanından tüm fonksiyonları ve değişkenleri çağırıyorsunuz. namespace stdİçinde bulunan başka bir işlevle aynı ada sahip yeni bir işlev tanımlamak istediğinizde, işlevi aşırı yüklersiniz ve derleme veya yürütme nedeniyle sorunlara neden olabilir. Beklediğiniz gibi derlenmeyecek veya yürütülmeyecektir.

Bu sayfada belirtildiği gibi :

Her ne kadar deyim std ad alanında tanımlanan bir sınıfa veya türe erişmek istediğimizde std :: yazmaktan kurtarsa ​​da, std ad alanının tamamını programın geçerli ad alanına aktarır. Bunun neden bu kadar iyi bir şey olmadığını anlamak için birkaç örnek verelim

...

Şimdi gelişimin daha sonraki bir aşamasında, "foo" adlı bazı kütüphanelerde özel olarak uygulanan cout'un başka bir sürümünü kullanmak istiyoruz (örneğin)

...

Belirsizliğin nasıl olduğuna dikkat edin, cout hangi kütüphaneye işaret ediyor? Derleyici bunu algılayabilir ve programı derlemeyebilir. En kötü durumda program, derleyicinin hangi ad alanına ait olduğunu hiçbir zaman belirtmediğimiz için derleme yapabilir ancak yanlış işlevi çağırabilir.


8

Her koşulda mutlaka kötü bir uygulama olduğunu düşünmüyorum, ancak kullanırken dikkatli olmanız gerekiyor. Bir kitaplık yazıyorsanız, kitaplığınızın diğer kitaplıklarla kafaları kıstırmasını önlemek için muhtemelen ad alanına sahip kapsam çözümleme işleçlerini kullanmalısınız. Uygulama seviyesi kodu için, yanlış bir şey görmüyorum.


7

"Neden 'namespace std kullanılıyor?' C ++ 'da kötü bir uygulama mı gördünüz? "

Başka bir deyişle: Neden fazladan beş karakter yazmak bazıları tarafından hantal kabul ediliyor?

Örneğin bir parça sayısal yazılım yazmayı düşünün. Neden "vektör" sorun etki alanının en önemli kavramlarından biri olduğunda genel "std :: vector" u "vektör" e indirerek küresel ad alanımı kirletmeyi düşüneyim ki?


19
Bu sadece 5 ekstra karakter değil; standart kütüphanedeki herhangi bir nesne türüne her başvuruda bulunmanız durumunda 5 ekstra karakter. Hangi, standart kitaplığı çok sık kullanıyorsanız, sık sık olacaktır. Bu yüzden daha gerçekçi bir programda binlerce ekstra karakter. Muhtemelen kullanılabilmesi için dile 'kullanma' direktifi eklendi ...
Jeremy Friesner

5
Her seferinde 5 ekstra karakter değil, 5 karakter ve muhtemelen birkaç fare tıklayıp bir menüyü aşağı çekiyor ve istediğiniz düzenleyicide bir Bul ve Değiştir yapıyorsunuz.
DaveWalley

1
Okunabilirlik. cout << hex << setw(4) << i << endl;okumak daha kolaystd::cout << std::hex << std::setw(4) << i << std::endl;
oz1cz

16
Ve daha da kötüsü: std::map<std::string,std::pair<std::string,std::string>>ile karşılaştırıldığında korkunç map<string,pair<string,string>>.
oz1cz

4
STL kaplarınızı zaten tanımlamak iyi bir uygulamadır, bu yüzden std :: gerçekten önemli değil. Ve C ++ 11, örneğin yineleyicileri kullanırken işleri daha da kolaylaştıran otomatik anahtar kelimeyi bize getirdi.
juzzlin

7

Başkalarına katılıyorum - isim çatışmaları, belirsizlikler istiyor ve gerçek şu ki daha az açık. Ben kullanımını görebilirken, usingkişisel tercihim bunu sınırlamak. Ayrıca bazılarının dikkatini çekenleri de dikkate alacağım:

Eğer oldukça yaygın isim olabilecek bir işlev adı bulmak istiyorum, ama sadece bunu bulmak istiyorsanız stdad (veya ters - sen tüm çağrıları değiştirmek istiyorum değil ad std, ad X, ...), o zaman bunu nasıl yapmayı öneriyorsun?

Bunu yapmak için bir program yazabilirsiniz, ancak projenizi sürdürmek için bir program yazmak yerine, projenizin üzerinde çalışmak için zaman harcamak daha iyi olmaz mıydı?

Şahsen, aslında std::öneki önemsemiyorum . Görünüşe sahip olmamaktan çok hoşlanıyorum. Bunun açık ve bana "bu benim kodum değil ... Ben standart kütüphane kullanıyorum" ya da başka bir şey olup olmadığını söylüyor, çünkü bilmiyorum ama daha güzel görünüyor düşünüyorum. Bu son zamanlarda C ++ 'a girdiğim için garip olabilir (C ve diğer dilleri daha uzun süre kullanıyorum ve hala yapıyorum ve C, tüm zamanların en sevdiğim dilidir, derlemenin hemen üstünde).

Yukarıdakilerle ve diğerlerinin işaret ettiği şeyle ilgili olmasına rağmen başka bir şey daha var. Bu kötü bir uygulama olsa da, bazen std::nameprograma özel uygulama için standart kütüphane sürümü ve adı için ayırırım. Evet, bu gerçekten sizi ısırıp sert bir şekilde ısırırdı, ama hepsi bu projeyi sıfırdan başlattığımdan kaynaklanıyor ve bunun için tek programcıyım. Örnek: Aşırı yüklüyorum std::stringve çağırıyorum string. Yararlı eklemelerim var. Kısmen C ve Unix (+ Linux) küçük harfli isimlere olan eğilimim nedeniyle yaptım.

Bunun yanı sıra, ad alanı takma adlarınız olabilir. İşte size atıfta bulunulmamış olabileceği faydalı bir örnek. C ++ 11 standardını ve özellikle libstdc ++ ile kullanıyorum. Tam bir std::regexdesteği yok. Elbette derler, ancak programın sonunda bir hata olduğu satırları boyunca bir istisna atar. Ancak uygulama eksikliği.

İşte böyle çözdüm. Boost's regex yükleyin ve bağlayın. Sonra, libstdc ++ tamamen uygulandığında, ben sadece bu bloğu kaldırmak gerekir ve kod aynı kalır:

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

Bunun kötü bir fikir olup olmadığını tartışmayacağım. Ben ancak için temiz tutar olduğunu iddia edecektir benim proje ve aynı zamanda belirli yapar: Doğru, ben kullanım Boost zorunda ama ben libstdc gibi kullanıyorum ++ eninde sonunda olacaktır. Evet, kendi projenizi başlatmak ve başlangıçta bir standart (...) ile başlamak, bakım, geliştirme ve projeyle ilgili her şey için çok uzun bir yol kat ediyor!

Sadece bir şeyi açıklığa kavuşturmak için: Aslında bir sınıfın adını / STL'de kasten ve daha spesifik olarak yerine kullanmanın iyi bir fikir olduğunu düşünmüyorum . 'String' fikrini beğenmediğim için dize benim için istisnadır (ilk, yukarıda veya ikinciyi burada görmezden gelin, pun).

Olduğu gibi, hala C'ye karşı önyargılıyım ve C ++ 'a karşı önyargılıyım. Dikkat çeken ayrıntılar, üzerinde çalıştığım şeylerin çoğu C'ye daha fazla uyuyor (ama kendimi bir başka dil öğrenmek ve b. Daha iyi ifade edilen nesneye / sınıflara / vb. daha az kapalı fikirli, daha az kibirli ve daha kabul edicidir.). Ama ne olduğunu ben yapmak için sanki bir isim çatışması neden olur adına iki (aynı şey) sıralamak ben gerçekten listesini kullanın yoktur ve (, oldukça jenerik değil mi edilir?): Kullanışlı bazıları zaten önerilen budur using namespace std;ve bu yüzden bu amaçla spesifik olmayı, kontrolde olmayı ve standart kullanım olmayı planlıyorsam, bunu belirtmem gerektiğini bilmek istiyorum. Basitçe söylemek gerekirse: varsayım yok.

Ve Boost'un normal ifadesinin bir parçası haline gelmeye gelince std. Bunu gelecekteki entegrasyon için yapıyorum ve - yine, bunun tamamen önyargı olduğunu itiraf ediyorum - bunun kadar çirkin olduğunu düşünmüyorum boost::regex:: .... Gerçekten, bu benim için başka bir şey. C ++ 'da hala görünüşte ve yöntemlerde tam olarak kabul etmek için gelmediğim pek çok şey var (başka bir örnek: varadik şablonlar var değişkenlere karşı [ben varadik şablonları çok çok yararlı olduğunu itiraf ediyorum!]). Kabul ettiğim kişiler bile zor oldu ve hala onlarla ilgili sorunlarım var.



7

Deneyimlerime göre, diyen çok sayıda kitaplığınız varsa cout, ancak farklı bir amaç için yanlış kullanabilirsiniz cout.

Örneğin, ben yazarsanız, using namespace std;ve using namespace otherlib;sadece yazın coutziyade, (her ikisi de içinde olmak olur) std::cout(veya 'otherlib::cout'), yanlış birini kullanın ve hataları alabilirsiniz. Kullanımı çok daha etkili ve verimli std::cout.


6

Niteliksiz içe aktarılan tanımlayıcılarla , tanımlayıcıların nerede bildirildiğini öğrenmek için grep gibi harici arama araçlarına ihtiyacınız vardır. Bu, program doğruluğu hakkında muhakemeyi zorlaştırır.


6

Bulunduğu yere bağlıdır. Ortak bir başlıksa, ad alanının değerini genel ad alanına birleştirerek azaltırsınız. Unutmayın, bu modül globalleri oluşturmanın düzgün bir yolu olabilir.


6

Bu genellikle küresel ad alanı kirliliği olarak bilinen kötü bir uygulamadır. Birden fazla ad alanı imzayla aynı işlev adına sahip olduğunda sorunlar oluşabilir, daha sonra derleyicinin hangisini arayacağına karar vermesi belirsiz olacaktır ve işlev çağrınızla ad alanını belirttiğinizde bunlardan kaçınılabilir std::cout. Bu yardımcı olur umarım. :)


5

Sorunuzu cevaplamak için pratik olarak bu şekilde bakıyorum: bir çok programcı (hepsi değil) ad alanı std'yi çağırıyor. Bu nedenle, ad alanı std'dekiyle aynı adları çarpan veya kullanan şeyleri KULLANMAYIN alışkanlığı içinde olmalıdır. Bu büyük ölçüde kabul edilir, ancak kesin olarak konuşulabilecek olası tutarlı kelime ve takma adların sayısıyla karşılaştırıldığında çok fazla değildir.

Demek istediğim ... "bu varlığa güvenmeyin" demek, sadece var olmamıza güvenmek için sizi kuruyor. Kod snippet'lerini ödünç alıp sürekli onaran sorunlar yaşayacaksınız. Sadece kullanıcı tanımlı ve ödünç aldığınız şeyleri olması gerektiği gibi sınırlı bir kapsamda tutun ve ÇOK küreseller ile koruma (dürüst küreseller hemen hemen her zaman "şimdi derleyin, akıl sağlığı daha sonra" amacıyla son çare olmalıdır). Gerçekten std kullanarak "cout" hem de "std :: cout" için işe yarayacaktır çünkü std kullanarak değil sadece "std :: cout" için işe yarayacağını öğretmenin kötü tavsiye olduğunu düşünüyorum. Her zaman kendi kodunuzu yazacak kadar şanslı olmayacaksınız.

NOT: Derleyicilerin nasıl çalıştığını gerçekten öğrenene kadar verimlilik sorunlarına çok fazla odaklanmayın. Küçük bir kodlama deneyimiyle, iyi kodu basit bir şeye ne kadar genelleştirebildiklerini fark etmeden önce onlar hakkında o kadar çok şey öğrenmek zorunda değilsiniz. Her şeyi C dilinde yazdığınız kadar basit. İyi kod olması gerektiği kadar karmaşıktır.


Kaç halkın yararlı standart kütüphane işlevlerinden habersiz olduğu göz önüne alındığında ( <algorithm>örneğin, şeyleri yeniden icat etmek ), aynı kişilerin bu tanımlayıcılardan güvenilir bir şekilde kaçınabileceğini hayal etmek biraz zor görünüyor. Kendi kodunuzu gözden geçirin ve asla bir değişken veya fonksiyonunuz olmadığını söyleyin count. Veya distance, ya da log, destroy, launch, visit, beta, sample, messages, clamp, erase, copy, modulus, left, vb henüz tüm tanımlayıcıları cabası stdC ++ 35 çıktığında ... kodunuzu kıracak
Toby Speight'ın
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.