Std Ad Alanını Kullanma


110

Std isim alanına göre 'kullanmak' konusunda farklı görüşler var gibi görünüyor.

Bazıları ' using namespace std' kullan diyor , diğerleri kullanmamayı söylüyor, bunun yerine ' std::' ile kullanılacak std işlevlerinin önekini kullanırken diğerleri şöyle bir şey kullanıyor:

using std::string;
using std::cout;
using std::cin;
using std::endl;
using std::vector;

kullanılacak tüm standart işlevler için.

Her birinin artıları ve eksileri nelerdir?




Yanıtlar:


131

Çoğu C ++ kullanıcıları oldukça mutlu okuma vardır std::string, std::vectorbir çiğ gören Aslında, vb vectorbu olup olmadığını merak yapar std::vectorveya farklı bir kullanıcı tanımlı vector.

Ben her zaman kullanmaya karşıyım using namespace std;. Her tür adı küresel ad alanına aktarır ve her türden bariz olmayan belirsizliklere neden olabilir.

İşte stdad alanında bulunan bazı yaygın tanımlayıcılar : sayma, sıralama, bulma, eşitleme, ters çevirme. Yerel bir değişkene sahip olmak, bunun yerine kullanmanıza izin vermeyecek countanlamına gelir .using namespace stdcountstd::count

İstenmeyen ad çatışmasının klasik örneği aşağıdaki gibidir. Yeni başlayan biri olduğunuzu ve bilmediğinizi hayal edin std::count. Ya başka bir şey kullandığınızı <algorithm>ya da görünüşte ilgisiz bir başlık tarafından içeri alındığını hayal edin .

#include <algorithm>
using namespace std;

int count = 0;

int increment()
{
    return ++count; // error, identifier count is ambiguous
}

Hata genellikle uzun ve dostça değildir çünkü std::countbazı uzun iç içe türlere sahip bir şablondur.

Yine de sorun değil, çünkü std::countgenel ad alanına giriyor ve sayım işlevi bunu gizliyor.

#include <algorithm>
using namespace std;

int increment()
{
    static int count = 0;
    return ++count;
}

Belki biraz şaşırtıcı bir şekilde, bu sorun değil. Bir bildirim kapsamına aktarılan tanımlayıcılar, hem tanımlandıkları yeri hem de içe aktarıldıkları yeri içeren ortak ad alanında görünür. Başka bir deyişle, genel ad alanında std::countolduğu gibi görünür count, ancak yalnızca içinde increment.

#include <algorithm>

int increment()
{
    using namespace std;
    static int count = 0;
    return ++count;
}

Ve benzer nedenlerden dolayı countburada belirsizdir. using namespace stdneden olmaz std::count, dışını countbeklendiği gibi gizleyin . using namespaceBu kural araçlarının std::countgörünüyor (içinde incrementolarak işlevine) aynı kapsamda küresel kapsam, yani en ilan edildi sanki int count = 0;dolayısıyla belirsizlik neden ve.

#include <algorithm>

int count = 0;

int increment()
{
    using namespace std;
    return ++count; // error ambiguous
}

21
ancak std :: önek olmadan soooo yazmayı çok daha kolay!
xtofl

69
@xtofl: Hayır değil. Yazarken beş karakter o kadar alakalı değildir, ancak bu beş karakter okurken çok alakalı olabilir. Ve okuma kolaylığı, kaynak kod için yazma kolaylığından çok daha önemlidir, çünkü kod yazılandan çok daha fazla okunur.
sbi

3
Using ifadesinin kapsam kuralları ile doğru davrandığını ekleyebilirsiniz.
Martin York

2
@Martin York: Kapsam belirleme kurallarını gösteren örneklerle güncellendi. @Michael Burr: Muhtemelen o kadar da kötü değil, gerçekten hoşlanmadığım şey basit hatalar için verilen hata mesajlarının yorumlanmasının çok daha zor olduğu ya da hiç olmadığı. Örneğin, bir işlevin kapsam içinde olduğuna inanılır, ancak değildir ve bir std :: işlevi, yararlı bir 'tanımlayıcı tanınmadı' hatası almak yerine, genellikle daha belirsiz bir 'bağımsız değişkeni dönüştüremezsiniz' hatasıyla karşılaşırsınız X 'veya' şablondan işlev üretilemiyor 'stil hatası. Daha kötüsü, yanlış bir işlevin sessizce çağrılmasıdır. Nadirdir ama olur.
CB Bailey

5
Pekala, seçeneği hakkında kimsenin tartışmamasına şaşırdım using std::xxx;. İsim alanı kirliliği yapmaz, kod yazmak daha kısa olur ve bence copydaha okunaklı std::copy.
legends2k

41

Temelleri hariç tutma (Tüm stl nesnelerinin / işlevlerinin std :: infront eklemesi ve 'ad alanı std kullanmıyorsanız' daha az çakışma ihtimali)

Asla koymamanız gerektiğini de belirtmekte fayda var.

using namespace std

Bir başlık dosyasında, bu ad alanını kullanmak istemeseler bile bu başlık dosyasını içeren tüm dosyalara yayılabilir.

Bazı durumlarda aşağıdaki gibi şeyler kullanmak çok faydalıdır

using std::swap

Takas işleminin özel bir sürümü varmış gibi, derleyici bunu kullanacak, aksi takdirde geri dönecektir std::swap.

Eğer ararsanız std::swap, her zaman temel sürümü kullanırsınız, bu da optimize edilmiş sürümü çağırmaz (eğer varsa).


10
Bahsetmek için +1 using std::swap(şimdiye kadar kullandığım tek şey).
sbi

1
Yayılabileceğinden bahsettiği için +1 u n s. Sadece doğru bir şekilde oluşturulmuş başlıklara da girebileceğini not etmek için: Sadece sahte bir başlıktan sonra eklenmeleri gerekir.
quamrana

1
Ancak bir swapveya move(veya hash, lessvb.) Uzmanlık tanımlıyorsanız , bu uzmanlığı namespace stdyine de koymalısınız. Örneğin:namespace std {template<> class hash<X> {public: size_t operator()(const X&) const};} class X: {friend size_t std::hash<X>::operator()(const X&)};
AJMansfield

28

İlk olarak, bazı terminoloji:

  • kullanım beyanı : using std::vector;
  • kullanma yönergesi : using namespace std;

Bir başlık dosyasında genel kapsamda kullanılmadıkları sürece kullanma yönergelerini kullanmanın iyi olduğunu düşünüyorum . Yani sahip olmak

using namespace std;

.cpp dosyanız gerçekten bir sorun değildir ve eğer ortaya çıkarsa, tamamen sizin kontrolünüzdedir (ve hatta istenirse belirli blokları kapsayabilir). Kodu bir dizi std::niteleyici ile karıştırmak için özel bir neden göremiyorum - bu sadece bir grup görsel gürültüye dönüşüyor. Bununla birlikte, stdkodunuzda ad alanından bir grup ad kullanmıyorsanız , yönergeyi atlamakta da bir sorun görmüyorum. Bu bir totolojidir - direktif gerekli değilse, kullanmaya gerek yoktur.

Benzer şekilde, ad alanındaki belirli türler için birkaç kullanma bildirimi ( kullanma yönergeleri yerine ) ile stdidare edebiliyorsanız, o zaman yalnızca bu belirli adları mevcut ad alanına getirmemeniz için hiçbir neden yoktur. Aynı şekilde, tek bir kullanım yönergesi de işe yarayacaksa, 25 veya 30 kullanım bildirimine sahip olmanın çılgınca ve defter tutma zahmeti olacağını düşünüyorum.

Ayrıca , using-bildirimi kullanmanız gereken zamanlar olduğunu da unutmamak gerekir . Scott Meyers'in "Madde 25: Etkili C ++, Üçüncü Sürüm'den atmasız bir takas için desteği düşünün" konusuna bakın. Genel, şablonlu bir işleve sahip olmak için, parametreleştirilmiş bir tür için 'en iyi' takas yöntemini kullanmak için, kullanım bildiriminden ve bağımsız değişkene bağlı aramadan (ADL veya Koenig araması olarak da bilinir) yararlanmanız gerekir:

template< typename T >
void foo( T& x, T& y)
{
    using std::swap;     // makes std::swap available in this function

    // do stuff...

    swap( x, y);         // will use a T-specific swap() if it exists,
                         //  otherwise will use std::swap<T>()

    // ...
 }

Sanırım ad alanlarından önemli ölçüde yararlanan çeşitli diller için ortak deyimlere bakmalıyız. Örneğin, Java ve C # büyük ölçüde ad alanlarını kullanır (muhtemelen C ++ 'dan daha fazla). Ad alanları içindeki adların bu dillerde kullanılmasının en yaygın yolu, onları bir using-yönergesinin eşdeğeri ile toplu halde mevcut kapsama getirmektir. Bu, yaygın sorunlara yol açmaz ve birkaç kez sorun olduğu durumlarda, söz konusu isimlerle tam nitelikli isimlerle veya takma adlarla işlenerek bir 'istisna' temelinde ele alınır - tıpkı C ++ 'da yapılabileceği gibi.

Herb Sutter ve Andrei Alexandrescu, C ++ Coding Standards: 101 Rules, Guidelines ve Best Practices adlı kitabının "Madde 59: Ad alanı kullanımlarını bir başlık dosyasına veya bir #include'dan önce yazmayın" adlı kitabında şöyle derler:

Kısaca: Yönergelerden sonra uygulama dosyalarınızda bildirimleri ve yönergeleri özgürce kullanarak ad alanını kullanabilir ve kullanmalısınız #includeve bu konuda iyi hissetmelisiniz. Aksine tekrarlanan iddialara rağmen, bildirimleri ve yönergeleri kullanan ad alanı kötü değildir ve ad alanlarının amacını bozmazlar. Aksine, ad alanlarını kullanılabilir kılan şey onlardır.

Stroupstrup, "The C ++ Programming Language, Third Edition" da "Global isim alanını kirletmeyin" şeklinde sıklıkla alıntılanır. Aslında bunu söylüyor (C.14 [15]), ancak C.10.1 bölümüne atıfta bulunarak şöyle diyor:

Bir kullanım bildirimi yerel bir kapsama bir ad ekler. Bir kullanma yönergesi sağlamaz; yalnızca bildirildikleri kapsamdaki adları erişilebilir kılar. Örneğin:

namespaceX {
    int i , j , k ;
}

int k ;
void f1()
{
    int i = 0 ;

    using namespaceX ; // make names from X accessible

    i++; // local i
    j++; // X::j
    k++; // error: X::k or global k ?

    ::k ++; // the global k

    X::k ++; // X’s k
}

void f2()
{
    int i = 0 ;

    using X::i ; // error: i declared twice in f2()
    using X::j ;
    using X::k ; // hides global k

    i++;
    j++; // X::j
    k++; // X::k
}

Yerel olarak beyan edilen bir isim (ya sıradan bir beyanname ile ya da bir kullanım beyanı ile beyan edilen) aynı isimdeki yerel olmayan beyanları gizler ve ismin herhangi bir yasadışı aşırı yüklemesi beyan noktasında tespit edilir.

İçin belirsizlik hatası Not k++içinde f1(). Global adlar, global kapsamda erişilebilir hale getirilen ad alanlarındaki adlara tercih edilmez. Bu, yanlışlıkla yapılan ad çatışmalarına karşı önemli koruma sağlar ve - daha da önemlisi - küresel ad alanını kirletmenin hiçbir avantajının olmamasını sağlar.

Birçok isim bildiren kütüphaneler, kullanım yönergeleri aracılığıyla erişilebilir hale getirildiğinde, kullanılmayan isimlerin çatışmalarının hata olarak görülmemesi önemli bir avantajdır.

...

Geleneksel C ve C ++ programlarına kıyasla ad alanlarını kullanan yeni programlarda global adların kullanımında radikal bir düşüş görmeyi umuyorum. Ad alanlarının kuralları, küresel adların "tembel" bir kullanıcısına, küresel kapsamı kirletmemeye özen gösteren birine göre hiçbir avantaj sağlamayacak şekilde özel olarak hazırlanmıştır.

Ve 'küresel isimlerin tembel bir kullanıcısı' ile aynı avantaja nasıl sahip olunur? Bir ad alanındaki adları güvenli bir şekilde geçerli kapsam için kullanılabilir kılan using-yönergesinden yararlanarak .

Bir ayrım var Not o - isimleri stdbir kullanma-direktifi doğru kullanımı ile kapsamı hazır ad (sonra yönergesini koyarak #includesetmez) değil genel ad alanını kirletmektedir. Sadece bu isimleri kolayca ve çatışmalara karşı korumayı sürdürüyor.


Son noktanızla ilgili olarak: Java ve C # ayrıca çok daha düzgün ad alanlarına sahiptir. BCL'deki her şey Sistemde yaşıyorsa, "Sistemin kullanılması", "ad alanı std kullanımı" kadar soruna neden olur.
Jeff Hardy

Ancak gördüğüm Java ve C # programları, yalnızca "Sistem" (veya eşdeğeri) değil, genellikle kullandıkları tüm ad alanlarını getiriyor. Dolayısıyla, kullanılan tüm isimleri bir araya getiren tek bir kullanım yönergesi yerine, aşağı yukarı aynı şeyi yapan 5 veya 10 vardır. Ayrıca "std ad alanını kullanma" yapar; gerçekten bu kadar sorun yaratıyor mu?
Michael Burr

Sorun, std'nin çok fazla ortak ada sahip olması ve bir standart başlık dahil olmak üzere diğerinin tümünü içermesidir. Neyin ithal edildiği konusunda iyi bir kontrole sahip değiliz, çok fazla risk var. Java ve C # hakkında yeterince bilgim yok, ancak C ++ 'dan çok daha iyi bir modül sistemine sahip olan ve isimleri içe aktarmanın genellikle hoş karşılanmadığı Ada'yı biliyorum. Genel olarak, ilki bir adlandırma kuralı meselesidir (insanların öneki ve ad alanını kullanan, içe aktarmanın anlamsız olduğunu gördüm) sonra stil.
AProgrammer

1
Hala bunun gerçek dünya sorunu olduğuna ikna olmadım. Kullanım yönergelerinin her zaman ciddi dezavantajlar olmadan kullanıldığını görüyorum. Sonra tekrar, bir problemim yok değil bunları kullanarak. Ben sadece std::niteleyicilerin kodu karıştırmamasını tercih ediyorum - bundan kaçınmanın başka yolları da var (kullanım-bildirimleri veya yazım biçimleri genellikle işe yarar).
Michael Burr

1
@AProgrammer: "liste, bir lisp yorumlayıcıdaki listeyi tanımlamak için doğal bir tanımlayıcıdır" diyorsunuz - ancak " using namespace std;" yönergesine sahip olmak, doğal tanımlayıcınızı bildirmenizi engellemez ' list' - sadece yaparsanız, yapamazsınız std::listnitelendirmeden daha uzun kullanım . Bu " using namespace std;" direktif olmaması durumundan farklı değildir . Yoksa bir şey mi kaçırıyorum?
Michael Burr

17

Bir başlık dosyasında asla genel kapsamda ad alanı kullanmayın. Bu, çatışmaya yol açabilir ve çatışmanın göründüğü dosyadan sorumlu kişinin neden üzerinde hiçbir kontrolü yoktur.

Uygulama dosyasında, seçenekler çok daha az kesilir.

  • Bir ad alanı kullanmak std koymak o ad alanlarından tüm sembolleri getirir. Eklenecek sembollerden bahsetmeden neredeyse hiç kimse orada bulunan tüm sembolleri bilmediğinden (bu nedenle pratikte hiçbir çatışma politikasına sahip olmak imkansızdır) bu sorunlu olabilir. Ve C ++ standardı, bir başlığın diğer başlıklardan semboller eklemesine izin verir (C biri buna izin vermez). Kontrollü durumda yazmayı basitleştirmek için pratikte hala işe yarayabilir. Ve bir hata meydana gelirse, sorunlu dosyada tespit edilir.

  • Std :: name kullanarak koymak; bilinmeyen sembolleri içe aktarma riski olmadan yazmanın basitliği avantajına sahiptir. Bunun maliyeti, istenen tüm sembolleri açıkça içe aktarmanız gerektiğidir.

  • Açıkça nitelendirme biraz dağınıklık katıyor, ancak bazı pratiklerin daha az sorun olduğunu düşünüyorum.

Projemde, tüm isimler için açık nitelendirme kullanıyorum, std :: name kullanmayı kabul ediyorum, ad alanı std kullanımına karşı mücadele ediyorum (kendi liste türüne sahip bir lisp yorumlayıcımız var ve bu nedenle çakışma kesin bir şeydir).

Diğer ad alanları için, kullanılan adlandırma kurallarını da dikkate almanız gerekir. İsim alanı (sürüm oluşturma için) ve isimlerde önek kullanan bir proje biliyorum. Bir Doing using namespace Xsonra neredeyse risksiz ve bunu yaparken değil aptal görünümlü kod yol açar PrefixNS::pfxMyFunction(...).

Sembolleri içe aktarmak istediğiniz bazı durumlar vardır. std :: swap en yaygın durumdur: std :: swap'ı içe aktarırsınız ve ardından niteliksiz swap kullanırsınız. Bağımsız değişkene bağlı arama, varsa türün ad alanında uygun bir takas bulacak ve yoksa standart şablona dönecektir.


Düzenle:

Michael Burr, yorumlarda çatışmaların gerçek dünyada olup olmadığını merak ediyor. İşte gerçek bir canlı örnek. Bir lisp lehçesi olan bir uzantı dilimiz var. Tercümanımızda lisp.h içeren bir include dosyası var

typedef struct list {} list;

Aşağıdaki gibi görünen bazı kodları (buna "motor" adını vereceğim) entegre edip uyarlamamız gerekiyordu:

#include <list>
...
using std::list;
...
void foo(list const&) {}

Biz de şu şekilde değiştirdik:

#include <list>

#include "module.h"
...
using std::list;
...
void foo(list const&) {}

İyi. Her şey çalışıyor. Birkaç ay sonra, "module.h", "list.h" öğesini içerecek şekilde değiştirildi. Testler geçti. "modül", ABI'sini etkileyecek şekilde değiştirilmedi, bu nedenle "motor" kitaplığı, kullanıcılarını yeniden derlemeden kullanılabilirdi. Entegrasyon testleri iyiydi. Yeni "modül" yayınlandı. Bir sonraki motor derlemesi, kodu değiştirilmediğinde bozuldu.


1
Ad alanı kullanmanın kabul edilebilir olduğunu düşündüğüm kontrollü durumlardan biri kod yayınlamaktır. Sadeleştirme, sayfanın düzenini kolaylaştırır ve maruz kalan noktaya odaklanmaya yardımcı olur. Dezavantajı, gerçekten iyi bir uygulama göstermemesi, bu yüzden yeni başlayanlar için kitaplarda kullanmam.
AProgrammer

1
Std :: yazmanın netlik için ödenmesi gereken küçük bir bedel olduğunu düşünüyorum
paoloricardo

4
@paoloricardo: Öte yandan, std :: 'nin her yerde görünmesinin gereksiz görsel dağınıklık olduğunu düşünüyorum.
Michael Burr

1
@Michael: Paranı ödüyorsun ve seçimini yapıyorsun!
paoloricardo

2
Zaman ayırıp karşılaştığınız sorunun ayrıntılarını eklediğiniz için teşekkür ederiz.
Michael Burr

4

Kodunuzda std ve diğer kitaplıklarla ad çakışması riskiniz yoksa kullanabilirsiniz:

using namespace std;

Ancak kodunuzun belgelere bağımlılığını tam olarak bilmek istiyorsanız veya ad çakışması riski varsa, diğer yolu kullanın:

using std::string;
using std::cout;

Üçüncü çözüm, bu çözümleri kullanmayın ve koddaki her kullanımdan önce std :: yazın size daha fazla güvenlik sağlar, ancak belki kodda biraz ağırlık ...


4

Her ikisi de

using std::string;

ve

using namespace std;

genel ad alanına bazı semboller (bir veya birçok) ekleyin. Ve küresel ad alanına semboller eklemek , başlık dosyalarında asla yapmamanız gereken bir şeydir . Başlığınızı kimin dahil edeceğini kontrol edemezsiniz, diğer başlıkları (ve başlıkları içeren başlıkları içeren başlıkları vb.) İçeren çok sayıda başlık vardır.

Uygulama (.cpp) dosyalarında bu size bağlıdır (bunu yalnızca #include yönergelerinden sonra yapmayı unutmayın ). Bu belirli dosyadaki yalnızca kodu kırabilirsiniz, böylece ad çakışmasının nedenini yönetmek ve bulmak daha kolaydır. Tanımlayıcılardan önce std :: (veya başka herhangi bir önek kullanmayı tercih ederseniz, projenizde birçok ad alanı olabilir), sorun değil. Kullandığınız tanımlayıcıları global ad alanına eklemek isterseniz, sorun değil. Tüm ad alanını kafanıza getirmek istiyorsanız :-), bu size kalmış. Etkiler tek bir derleme birimiyle sınırlı olsa da, kabul edilebilir.


3

Benim için ::mümkün olduğunda kullanmayı tercih ediyorum .

std::list<int> iList;

Yazmaktan nefret ediyorum:

for(std::list<int>::iterator i = iList.begin(); i != iList.end(); i++)
{
    //
}

Umarım C ++ 0x ile şunu yazardım:

for(auto i = iList.begin(); i != iList.end(); i++)
{
    //
}

Ad alanı çok uzunsa,

namespace dir = boost::filesystem;

dir::directory_iterator file("e:/boost");
dir::directory_iterator end;

for( ; file != end; file++)
{
    if(dir::is_directory(*file))
        std::cout << *file << std::endl;
}

@AraK: ad alanı dir = boost :: dosya sistemi; Sanırım bu bir takma ad mı?
paoloricardo

@paoloricardo: Evet, öyle #.
sbi

2
Yineleyiciler ile artırılmalıdır ++i, i++çünkü tanımlanmış olsa bile yineleyicinin gereksiz geçici bir kopyasını oluşturur.
Felix Dombek

2

using namespace stdBir başlıkta asla ad alanı kapsamında olmamalısınız . Ayrıca, ben onlar görünce merak edecektir çoğu programcı varsayalım vectorveya stringolmadan std::Bence değil bu yüzden, using namespace stddaha iyidir. Bu yüzden asla olmamamı savunuyorum using namespace std.

Yapmanız gerektiğini düşünüyorsanız, gibi bildirimler kullanarak yerel ekleyin using std::vector. Ama kendinize sorun: Bunun değeri nedir? Bir kod satırı bir kez (belki iki kez) yazılır, ancak on, yüz veya bin kez okunur. Bir kullanma bildirimi veya yönergesi eklemek için kaydedilen yazma çabası, kodu okuma çabasına kıyasla marjinaldir.

Bunu akılda tutarak, on yıl önce bir projede tüm tanımlayıcıları tam ad alanı adlarıyla açık bir şekilde nitelendirmeye karar verdik. İlk başta garip görünen şey iki hafta içinde rutin hale geldi. Artık o şirketin tüm projelerinde kimse direktif veya beyanname kullanmıyor. (Bir istisna dışında, aşağıya bakın.) On yıl sonra koda (birkaç MLoC) baktığımızda, doğru kararı verdiğimizi hissediyorum.

Genelde, yasaklamaya karşı çıkanların usingbunu genellikle bir proje için denemediğini gördüm . Deneyenler, genellikle bunu çok kısa bir süre sonra direktifleri / bildirimleri kullanmaktan daha iyi bulurlar.

Not: Tek istisna using std::swap(özellikle jenerik kodda) aşırı yüklemeleri almak için swap()gerekli stdolandır (çünkü stdbu ad alanına fonksiyonların aşırı yüklemelerini koymamıza izin verilmemektedir ).


3
Std :: swap'ın bir uzmanlığı tam bir uzmanlık olacaktır - işlev şablonlarını kısmen özelleştiremezsiniz. Herhangi bir program olan , kısmen çok uzun olduğu uzmanlık kullanıcı tanımlı bir türüne bağlıdır gibi herhangi bir standart kütüphane numunesi uzmanlaşmış bırakıldı.
CB Bailey

@Charles: Evet, haklısın, elbette FTPS yok. Ve içindeki şablonları özelleştirebilirimstd , ancak aşırı yüklemem. O beyin osuruğu için özür dilerim. Gönderiyi düzelteceğim.
sbi

2
using namespaceYönergenin amacının da daktilo etmek olduğunu sanmıyorum ; daha ziyade okumayı kolaylaştırmak içindi , çünkü sizin de söylediğiniz gibi bu kodun onlarca, yüzlerce veya binlerce kez okunması gerekecek. Ve bazı insanlar için, daha az dağınıklıkla çok daha kolay okur std::. Ancak bu muhtemelen kişisel algılama yeteneğine bağlıdır; Bazı insanlar filtreleyerek std::uzaklaştırır, hatta rehberlik için buna ihtiyaç duyar (serifler gibi), diğerleri yanılsalar ve engebeli bir yolda hissederler.
Lumi


1
@sbi: Hayır, bu objektif değil. Bu, std :: 'nin yardımcı olup olmadığını veya karmaşayı düşündüğünüze bağlıdır. Daha fazla dağınıklık -> daha az netlik.
Joshua Richardson

2

Ad alanları , işlev imzalarının karıştırılmasını ve kirlenmesini önlemek için kodu içeride tutar .

İşte uygun ad alanı kullanımının eksiksiz ve belgelenmiş bir demosu :

#include <iostream>
#include <cmath>  // Uses ::log, which would be the log() here if it were not in a namespace, see /programming/11892976/why-is-my-log-in-the-std-namespace

// Silently overrides std::log
//double log(double d) { return 420; }

namespace uniquename {
    using namespace std;  // So we don't have to waste space on std:: when not needed.

    double log(double d) {
        return 42;
    }

    int main() {
        cout << "Our log: " << log(4.2) << endl;
        cout << "Standard log: " << std::log(4.2);
        return 0;
    }
}

// Global wrapper for our contained code.
int main() {
    return uniquename::main();
}

Çıktı:

Our log: 42
Standard log: 1.43508

1

using namespace stdstdmevcut ad alanının içeriğini içe aktarır . Bu nedenle, avantaj, std::o ad alanının tüm işlevlerinin önüne yazmanız gerekmeyecek olmasıdır. Ancak, aynı adı taşıyan işlevlere sahip farklı ad alanlarınız olabilir. Böylece istediğiniz kişiyi aramaya son verebilirsiniz.

Hangilerini içe aktarmak istediğinizi manuel olarak belirlemek, bunun olmasını stdengeller, ancak dosyanızın başında bazı geliştiricilerin çirkin bulacağı uzun bir kullanım listesine neden olabilir;)!

Kişisel olarak, ad alanının çok uzun olması dışında, bir işlevi her kullandığımda ad alanını belirtmeyi tercih ederim, bu durumda dosyanın başına bazılarını koyarım.

DÜZENLEME: Başka bir yanıtta belirtildiği gibi, using namespacebu başlık dahil tüm dosyalara yayılacağından ve bu nedenle istenmeyen davranışlara neden olabileceğinden, bir başlık dosyasına asla bir koymamalısınız.

EDIT2: Charles yorumu sayesinde cevabımı düzeltti.


2
using namespace std;stdad alanının içeriğini genel ad alanına aktarır . Varsayılan ad alanını değiştirmez. Global ad alanında a'dan sonra bir şey tanımlamak using namespace std, onu sihirli bir şekilde stdad alanına koymaz.
CB Bailey

Üzgünüm, demek istediğim bu değildi. Gösterdiğiniz için teşekkürler, cevabımı düzelteceğim.
Wookai

1
Beyler: Cevaplar için teşekkürler. Görünüşe göre, genel olarak, 'ad alanı std'yi kullanmamak ve olası belirsizlikler yaratmaktan kaçınmak daha güvenlidir. Dengeli olarak 'std :: xxx' kullanmak bana, kaynak dosyanın başında çeşitli işlevlerin bir listesini bildirmekten daha çok çekici geliyor çünkü bu, birinin amacının ne olduğunu açık bir şekilde nitelendiriyor.
paoloricardo

1
Alıntı (ad alanının çok uzun olduğu durumlar dışında). Burada yardımcı olması için ad alanı takma adını kullanabilirsiniz. 'ad alanı Rv1 = Thor :: XML :: XPath :: Rules :: Light :: Version1;' Diğer adları not edin ve her ikisini de kullanarak kapsam kurallarına uyun;
Martin York

0

Java'da olduğu gibi, her ikisini de kullanabileceğiniz java.util. * İçerebilir veya her sınıfı tek tek seçebilir, bu stile bağlıdır. using namespace stdDosyanızın / geniş kapsamınızın başında bir tane istemediğinizi unutmayın, çünkü ad alanını kirleteceksiniz ve muhtemelen ad alanlarının noktasını yenerek çatışmalar yaşayacaksınız. Ancak çok fazla STL kullanan bir işleviniz varsa, bu, mantığınızda karmakarışık bir önek sözdizimi olması için kodu karıştırır ve muhtemelen using namespace std(çeşitli sınıfları kullanırken) veya tek tek usings (birkaçını kullanırken ) kullanmayı düşünmelisiniz. sık sık).


0

Bu tartışma, birlikte çalıştığınız IDE tam olarak ihtiyacınız olan bilgileri gösterecek veya gizleyecek kadar esnek olmadığı sürece canlı kalacaktır.

Çünkü kodunuzun neye benzemesini istediğiniz, elinizdeki göreve bağlıdır.

Kaynak kodumu oluştururken, tam olarak hangi sınıfı kullandığımı görmeyi tercih ederim: bu mu std::stringyoksa BuzFlox::Obs::stringsınıf mı?

Kontrol akışını tasarlarken değişkenlerin türleriyle bile ilgilenmiyorum, ancak if's ve while' ler ve continue'ler üzerine odaklanmak istiyorum .

Yani bu benim tavsiyem:

Kodunuzun hedef kitlesine ve araçlarınızın gücüne bağlı olarak, en kolay okuma veya en çok bilgiyi veren yolu seçin.


0

Bunu düzeltmenin birkaç yolu var.

İlk olarak: yaptığınız gibi kullanın.

İkincisi: namespace S = std;2 karakter azaltarak yapın.

Üçüncüsü: kullanın static.

Dördüncüsü: kullanan isimler stdkullanmayın.


-1

Her birinin artıları ve eksileri nelerdir

Std :: 'yi devre dışı bırakmanın tek nedeni, teoride tüm STL işlevlerini kendiniz yeniden uygulayabilmenizdir. Daha sonra fonksiyonlarınız, kodu değiştirmeden std :: vector'den my :: vector'e değiştirilebilir.


Ad alanları, adların farklı ancak eşdeğer işlevlerle değiştirilmesine izin verecek şekilde tasarlanmamıştır. İstenmeyen isim çatışmalarını önlemek için tasarlanmıştır.
Michael Burr

Evet, bu yüzden bunu bozan 'using' direktifinin tek gerekçesi, işlevleri yeni bir ad alanına geçirmenize izin vermektir.
Martin Beckett

Sanırım çok sayıda programcı, ad alanlarında ne kadar sıkıntılı olduğundan şikayet eden ve bir kullanım yönergesi olmasa onları pencereden atmak isteyen çok sayıda programcı bulursunuz. Bildiğim kadarıyla, ad alanlarını kullanan her dilde, onları yoldan çekmeyi istediğinizde onları yoldan çıkarmak için bir kullanım yönergesine benzer bir şey vardır. Direktifler işe yaramazsa, neden her yerde varlar?
Michael Burr

Sanırım "kullanım", 3 harf yazarak kaydetmek yerine alternatif uygulamalara geçmenize izin vermek için tasarlandı. "Std :: Foo" kullanmayı seviyorum çünkü programcıya normal Foo'yu kullandığım ve kontrol etmek zorunda olmadıkları konusunda bir sözleşme görevi görüyor. "Com.microsoft.visual-studio.standard-library.numbers.int foo" yazmak zorunda kalmak istemediğime katılıyorum, STL'deki bazı yineleyici bildirimleri böyle oluyor. Python, modüllerden dekore edilmiş veya dekore edilmemiş işlev kümelerini çekmenize izin vermek için güzel bir iş çıkarır.
Martin Beckett

-1

Örneğin neden olmasın

typedef std::vector<int> ints_t;
ints_t ints1;
....
ints_t ints2;

hantal yerine

std::vector<int> ints1;
...
std::vector<int> ints2;

Bunu çok daha okunaklı buluyorum ve bu benim kodlama standardım.

Okuyucu için bazı anlamsal bilgiler eklemek için bile kullanabilirsiniz. Örneğin, fonksiyon prototiplerini düşünün

void getHistorgram(std::vector<unsigned int>&, std::vector<unsigned int>&);

hangileri dönüş değeri?

Onun yerine

typedef std::vector<unsigned int> values_t;
typedef std::vector<unsigned int> histogram_t;
...
void getHistogram(values_t&, histogram_t&); 
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.