Auto C ++ kodunun anlaşılmasını zorlaştırır mı?


122

Herb Sutter tarafından her C ++ programcısını kullanmaya teşvik ettiği bir konferans gördüm auto.

Bir süre önce C # kodunu okumak zorundaydım, burada varçokça kullanılıyordu ve kodun anlaşılması çok zordu - her seferinde varsağ tarafın dönüş tipini kontrol etmek zorunda kaldım. Bazen bir kereden fazla, bir süre sonra değişkenin tipini unuttum çünkü!

Derleyicinin türünü bildiğini ve yazmam gerekmediğini biliyorum, ancak derleyiciler için değil, programcılar için kod yazmamız gerektiği kabul edilir.

Ayrıca yazmanın daha kolay olduğunu da biliyorum:

auto x = GetX();

daha:

someWeirdTemplate<someOtherVeryLongNameType, ...>::someOtherLongType x = GetX();

Ancak bu yalnızca bir kez yazılır ve GetX()ne tür olduğunu anlamak için dönüş türü birçok kez kontrol edilir x.

Bu beni meraklandırdı - autoC ++ kodunun anlaşılmasını zorlaştırıyor mu?


29
Her seferinde geri dönüş tipini kontrol etmeniz gerekiyor mu? Tip neden koddan anlaşılmıyor? autoZaten çoğu zaman okunması zor olan şeyleri okumayı zorlaştırır, yani çok uzun, fonksiyonlar çok az adlandırılmış değişkenler, vb.
R. Martinho Fernandes

25
Kullanmanın "sanatı" autone zaman kullanılacağını belirlemeye benzer typedef. Ne zaman engelleyeceğini ve ne zaman yardımcı olacağını belirlemek size kalmıştır.
ahenderson

18
Aynı sorunu yaşadığımı sanıyordum, ancak sonra türlerini bilmeden sadece kodu anlayabileceğimi fark ettim. örneğin: "auto idx = get_index ();" Yani idx bir indeksi tutan bir şeydir. Kesin tip nedir, çoğu durumda oldukça önemsizdir.
PlazmaHH

31
Bu yüzden yazmayın auto x = GetX();, daha iyi bir isim seçin x, aslında bu bağlamda ne yaptığını söyler ... bu genellikle türünden daha faydalıdır.
Jonathan Wakely

11
Daha fazla tür çıkarım kullanmak, bir programcının kodu okumasını zorlaştırıyorsa, kodun veya programcının ciddi şekilde iyileştirilmesi gerekir.
CA McCann

Yanıtlar:


99

Kısa cevap: Daha ayrıntılı olarak, şu andaki görüşüm açıkça bir dönüşüm istemiyorsanız varsayılan olarak autokullanmanız gerektiği yönünde auto. (Biraz daha kesin olarak, "... açıkça bir tür işlemek istemiyorsanız, neredeyse her zaman bir dönüşüm istediğinizden gelir.")

Daha uzun cevap ve gerekçe:

Açık bir tür ( autoyalnızca değil ) yalnızca bir türe gerçekten açıkça söz vermek istediğinizde yazın; bu, neredeyse her zaman açıkça o türe dönüşüm elde etmek istediğiniz anlamına gelir. Başımın üstünden iki ana durumu hatırlıyorum:

  • (Ortak) Düşüren initializer_listsürpriz . İstemiyorsanız , şunu yazın - yani, açıkça bir dönüşüm isteyin.auto x = { 1 };initializer_listinitializer_list
  • (Nadir) İfade şablonları örneği, auto x = matrix1 * matrix 2 + matrix3;programcı tarafından görülmeyen bir yardımcı veya vekil türünü yakalar gibi . Çoğu durumda, bu türün yakalanması gayet iyi ve zararlıdır, ancak bazen gerçekten çökmesini ve hesaplamayı yapmasını istiyorsanız, sonra şunu yazın - yani, açıkça açıkça bir dönüşüm isteyin.

autoAksi takdirde rutin olarak kullanın , çünkü kullanım autotuzaklar önler ve kodunuzu daha doğru, daha sürdürülebilir, daha sağlam ve daha verimli hale getirir. Kabaca en önemlisinden en önemlisine, "ilk önce açıklık ve doğruluk için yaz" ruhuyla:

  • Doğruluk:auto Garantileri kullanarak doğru tipi elde edersiniz. Söylemeye devam edersek, eğer kendinizi tekrar ederseniz (fazlalık söyleyin), yalan söyleyebilirsiniz ve yalan söyleyin (yanlış anlayın). Alışılmış bir örnek: void f( const vector<int>& v ) { for( /*…*- bu noktada, yineleyicinin türünü açıkça yazarsanız, yazmayı hatırlamak istersiniz const_iterator(yaptınız mı?), Oysa autodoğru yapar.
  • Bakım ve sağlamlık: Kullanma auto, kodunuzu değişiklik karşısında daha da sağlamlaştırır, çünkü ifadenin türü değiştiğinde, autodoğru türe çözümlenmeye devam edilir. Bunun yerine açık bir türe karar verirseniz, ifadenin türünü değiştirmek, yeni tür eski türe dönüştürüldüğünde sessiz dönüşümler ya da yeni tür hala eski türe benzeyen ancak eskiye dönüştürülmediğinde gereksiz derlemeler kesebilir türü (örneğin, ne zaman bir değişiklik mapbir için unordered_mapkullanmakta, sırayla güvenerek değilse her zaman ince olan autosorunsuz geçiş edeceğiz sizin yineleyiciler için map<>::iteratoriçin unordered_map<>::iterator, ama kullananmap<>::iterator her yerde açıkça, bir stajyerin yanından geçmediği ve sıkıcı işlerden vazgeçemediğiniz sürece, değerli zamanınızı bir mekanik kod düzeltme dalgalanmasına harcayacağınız anlamına gelir.
  • Performansı: Çünkü autogaranti örtülü hiçbir dönüşüm olacak, varsayılan olarak daha iyi performans garanti eder. Bunun yerine, türü söylerseniz ve bir dönüşüm gerektiriyorsa, bekleseniz de beklemeseniz de sessizce bir dönüşüm elde edersiniz.
  • Kullanılabilirlik: kullanma autotekrarlayan başvurmadan kısa tür lambdas ve şablon yardımcıları olarak-büyü-sert ve unutterable türleri, için sadece iyi seçenektir decltypeifadeleri ya da benzeri az verimli indirections std::function.
  • Kolaylık: Ve, evet, autodaha az yazıyor. Sonunculuktan bahsettim, çünkü beğenmek için ortak bir neden, ama onu kullanmak için en büyük sebep değil.

Dolayısıyla: autoVarsayılan olarak söylemeyi tercih edin . O kadar çok basitlik ve performans ve netlik iyiliği sunar ki, yapmazsanız sadece kendinize (ve kodunuzun gelecekteki koruyucuları) zarar vereceksiniz. Yalnızca gerçekten ciddiye aldığınızda kesin bir tür seçin, bu da neredeyse her zaman kesin bir dönüşüm istediğiniz anlamına gelir.

Evet, bu konuda (şimdi) bir GotW var.


14
Dönüşüm yapmak istediğimde bile otomatik olarak kullanışlı buluyorum. Bu beni açıkça türünü tekrarlamadan bir dönüşüm için sormak sağlar: auto x = static_cast<X>(y). static_castAçıkça dönüştürme amacına ve bu dönüşümü hakkında derleyici uyarılarını önler ortaya koyuyor. Normalde, derleyici uyarılarından kaçınmak o kadar iyi değildir, ancak yazarken dikkatle değerlendirdiğim bir dönüşüm hakkında uyarı alamadım static_cast. Şu anda herhangi bir uyarı yoksa bunu yapmazdım, ancak türler potansiyel olarak tehlikeli bir şekilde değişirse gelecekte uyarıları almak isterim.
Bjarke Hammersholt Roune

6
Bulduğum bir şey , belirli uygulamalara karşı değil, arayüzlereauto karşı (OOP anlamında değil) programlamaya çalışmamız gerektiğidir . Gerçekten de şablonlarda aynı. Her yerde kullanılan bir şablon tipi parametreniz olduğundan, "okunması zor kod" hakkında şikayet ediyor musunuz ? Hayır, sanmıyorum. Şablonlarda biz de bir arayüze karşı kod yazıyoruz, derleme zamanı ördek yazma işlemi birçok insanın dediği şey. T
Xeo,

6
"Otomatik garantileri kullanarak doğru tipini elde edersiniz." Hiç doğru değil. Yalnızca, kodunuzun diğer bölümlerinde belirtilen türü alacağınızı garanti eder. Bunun doğru olup olmadığı, onu geride sakladığınızda tamamen belirsizdir auto.
Orbit'teki Hafiflik Yarışları

Hiç kimsenin IDE'leri umursamadığıma gerçekten şaşırdım ... Modern IDE'ler bile autodeğişken durumunda sınıf / yapı tanımına atlamayı doğru şekilde desteklemiyor , ancak neredeyse tamamı açıkça açıkça belirtilen özelliklerle doğru şekilde yapıyor. Kimse IDE kullanmıyor mu? Herkes sadece int / float / bool değişkenlerini kullanır? Herkes kendi kendini belgeleyen başlıklar yerine kütüphaneler için dış belgeleri tercih ediyor mu?
avtomaton

Bu GotW: herbsutter.com/2013/08/12/… "initializer_list surprise" öğesinin nasıl bir sürpriz olduğunu anlamıyorum ; =RHS etrafındaki diş telleri, başka herhangi bir yorumdan pek bir anlam ifade etmiyor (çubuk takviyeli init-list, ancak ne başlattığınızı bilmeniz gerekiyor, ki bu da bir oksimorondur auto). Biri olan şaşırtıcı olduğunu auto i{1}da deducing initializer_listdeğil ima rağmen bu init-liste hazırladı almak ziyade bu ifadeyi almak ve türünü kullanmak ... ancak tanıtım initializer_listda orada. Neyse ki, C ++ 17 tüm bunları iyi düzeltir.
underscore_d

112

Bu duruma göre bir durum.

Bazen kodu anlamak bazen zorlaştırıyor. Mesela:

void foo(const std::map<int, std::string>& x)
{
   for ( auto it = x.begin() ; it != x.end() ; it++ )
   { 
       //....
   }
}

anlamak kesinlikle kolaydır ve gerçek yineleyici beyandan daha yazmak için kesinlikle daha kolay.

C ++ 'ı bir süredir kullanıyorum, ancak bu konuda ilk attığımda bir derleyici hatası alacağımı garanti edebilirim çünkü unutacağım const_iteratorve başlangıçta iterator...

Bu gibi durumlar için kullanırdım, ancak tipini gerçekten engellediği yerde değil (durumunuz gibi), ama bu tamamen özneldir.


45
Kesinlikle. Bu halt türü kimin umrunda. Bu bir tekrarlayıcı. Türü umrumda değil, bilmem gereken tek şey onu tekrarlamak için kullanabileceğim.
R. Martinho Fernandes,

5
+1. Türü isimlendirseniz std::map<int, std::string>::const_iteratorbile, ismini yazarsınız, bu yüzden isim size zaten bir şey söylemez.
Steve Jessop,

4
@ SteveJessop: Bana en azından iki şey söyler: anahtar intve değer std::string. :)
Nawaz

16
@Nawaz: ve it->secondbir const yineleyici olduğundan atamadığınız . Tüm bu bilgiler önceki satırdakilerin bir tekrarıdır const std::map<int, std::string>& x. Bazı şeyleri defalarca söylemek, bazen daha iyi bilgi verir, ancak hiçbir şekilde genel bir kural değildir :-)
Steve Jessop

11
TBH for (anX : x)Sadece yinelemekte olduğumuzu daha da netleştirmeyi tercih ederim x. Eğer bir yineleyici gerek normal bir durum size kabı modifiye ederken, ancak xbirconst&
MSalters

94

Buna başka bir yolla bak. Yazar mısın:

std::cout << (foo() + bar()) << "\n";

veya:

// it is important to know the types of these values
int f = foo();
size_t b = bar();
size_t total = f + b;

std::cout << total << "\n";

Bazen açıkça yazımın yapılmasına yardımcı olmaz.

Türden bahsetmeniz gerekip gerekmediği kararı, ara değişkenleri tanımlayarak kodu birden çok ifadeye bölmek isteyip istemediğinizle aynı değildir. C ++ 03 'te ikisi birbirine bağlandı, autoonları ayırmanın bir yolu olarak düşünebilirsiniz .

Bazen türleri açık yapmak yararlı olabilir:

// seems legit    
if (foo() < bar()) { ... }

vs.

// ah, there's something tricky going on here, a mixed comparison
if ((unsigned int)foo() < bar()) { ... }

Değişken bildirdiğiniz durumlarda auto, tür kullanımı birçok ifadede olduğu gibi söylenemez. Muhtemelen okunabilirliğe ne zaman ve ne zaman engel olacağına kendin karar vermeye çalışmalısın.

İmzalı ve imzasız türleri karıştırmanın başlangıçta bir hata olduğunu iddia edebilirsiniz (gerçekten de bazıları, birinin imzasız türleri kullanmaması gerektiğini ileri sürer). Nedeni bu tartışmalı bir hata nedeniyle farklı davranış işlenen tipleri hayati önem sağlamasıdır. Değerlerinizin türlerini bilmeniz gereken kötü bir şeyse, muhtemelen bunları bilmeniz gerekmeyen kötü bir şey değildir. Bu nedenle, kod zaten başka nedenlerle kafa karıştırıcı değilse, bu autodoğru, tamam mı? ;-)

Özellikle, genel kod yazarken, bir değişkenin gerçek tipinin önemli olmaması gereken durumlar vardır, önemli olan şey gerekli arayüzü sağlamasıdır. Bu nedenle auto, türü görmezden geldiğiniz bir soyutlama düzeyi sağlar (ancak derleyici bilmez). Uygun bir soyutlama seviyesinde çalışmak, okunabilirliğe epeyce yardımcı olabilir, “yanlış” seviyede çalışmak, kodu okumayı bir slogan haline getirir.


21
+1 auto, adsız veya ilginç olmayan türlerle adlandırılmış değişkenler oluşturmanıza olanak sağlar. Anlamlı isimler faydalı olabilir.
Mankarse

Doğru kullanım için imzasız kullanıyorsanız, imzalı ve imzasız karıştırma: modüler aritmetik. Olumsuz tamsayı için imzasız kötüye kullanırsanız, öyle değil. Neredeyse hiçbir programın imzasız kullanımı yoktur, ancak ana dil onun sizeofimzasız tanımını sizin için imzasız olarak zorlar .
curiousguy

27

IMO, buna tam tersi bakıyorsun.

autoOkunamayan ya da daha az okunabilen kodlara öncülük etmek meselesi değil . Geri dönüş değeri için açık bir türe sahip olmanın (umarız) meselesi, belirli bir fonksiyon tarafından hangi türün geri döneceğinin (görünüşe göre net olmadığı) ortaya çıkmasıdır.

En azından benim görüşüme göre, dönüş tipi hemen belli olmayan bir işleve sahipseniz, buradaki sorun budur. İşlevin yaptığı şey, adından açıkça anlaşılmalı ve dönüş değerinin türü, yaptığı şeyden açıkça anlaşılmalıdır. Değilse, sorunun asıl kaynağı budur.

Burada bir sorun varsa, sorun değil auto. Kodun geri kalan kısmı ile ilgilidir ve açık türün çekirdek problemi görmenize ve / veya düzeltmenize engel olmak için bir yara bandı için yeterli olması ihtimali oldukça iyidir. Bu sorunu düzelttikten sonra, kullanılan kodun okunabilirliği autogenellikle iyi olacaktır.

Dürüst olmak gerekirse eklemeliyim: Bu tür şeylerin istediğiniz kadar neredeyse net olmadığı birkaç sorunu ele aldım ve sorunu çözmek de oldukça makul değildi. Sadece bir örnek için, birkaç yıl önce daha önce başka bir şirketle birleşmiş olan bir şirkete danışmanlık yaptım. Gerçekten birleştirilenden daha "birlikte ittiği" bir kod üssü ile sonuçlandılar. Kurucu programlar, benzer amaçlar için farklı (ancak oldukça benzer) kütüphaneler kullanmaya başlamışlardı ve işleri daha temiz bir şekilde birleştirmek için çalışsalar da yine de yaptılar. Çok sayıda durumda, belirli bir işlev tarafından hangi türün döndürüleceğini tahmin etmenin tek yolu, bu işlevin nereden kaynaklandığını bilmekti.

Böyle bir durumda bile, bir kaç şeyi daha net hale getirmeye yardımcı olabilirsiniz. Bu durumda, tüm kod genel ad alanında başladı. Adil bir miktarın bazı ad alanlarına taşınması, ad çakışmalarını ortadan kaldırdı ve tür takibini de biraz kolaylaştırdı.


17

Genel kullanım için otomatik olarak beğenmeme neden olan birkaç neden var:

  1. Kodu değiştirmeden yeniden aktive edebilirsiniz. Evet, bu otomatik kullanmanın yararı olarak listelenen şeylerden biridir. Bir fonksiyonun dönüş tipini değiştirmeniz yeterlidir ve onu çağıran kodun tümü otomatik kullanılıyorsa, ek çaba göstermeniz gerekmez! Derlemeye bastığınızda, - 0 uyarı, 0 hata - oluşturur - ve sadece fonksiyonun kullanıldığı 80 yeri gözden geçirme ve potansiyel olarak değiştirme karmaşası ile uğraşmadan kodunuzu kontrol edin.

Bekle, bu gerçekten iyi bir fikir mi? Tür bu kullanım durumlarından yarım düzine kadar önemliyse ve şimdi bu kod gerçekten farklı davranıyorsa? Bu aynı zamanda, yalnızca girdi değerlerini değil, işlevi çağıran diğer sınıfların özel uygulamasının davranışını değiştirerek örtük olarak enkapsülasyonu da kırabilir.

1 A. "Kendini belgeleyen kod" kavramına inanıyorum. Kendi kendini belgeleyen kodun ardındaki sebep, yorumların eski haline gelme eğiliminde olması, artık kodun ne yaptığını yansıtmamasıdır, oysa kodun kendisi - açık bir şekilde yazılırsa - kendini açıklayıcıdır, daima güncel kalır. niyetine göre ve sizi eski yorumlarla karıştırmaz. Kodun kendisini değiştirmeye gerek kalmadan türler değiştirilebilirse, kod / değişkenlerin kendileri eski hale gelebilir. Örneğin:

auto bThreadOK = CheckThreadHealth ();

Sorunun dışında, CheckThreadHealth () 'in bir noktada bir bool yerine varsa hata durumunu gösteren bir enum değeri döndürmek için yeniden düzenlendi. Ancak bu değişikliği yapan kişi bu özel kod satırını incelemeyi kaçırdı ve derleyici hiçbir uyarı vermedi, çünkü herhangi bir uyarı veya hata olmadan derlendi.

  1. Asıl türlerin ne olduğunu asla bilemezsiniz. Bu aynı zamanda otomatik bir birincil "fayda" olarak listelenir. Neden bir işlevin size verdiğini, neden “Kim umrunda?

Muhtemelen bu tür işler bile. İşe yarar diyorum, çünkü her döngü yinelemesi için 500 baytlık bir yapı kopyasını çıkarsanız bile, üzerinde tek bir değer olup olmadığını kontrol edebilirsiniz, kod hala tamamen işlevseldir. Bu nedenle, birim testleriniz bile, kötü kodun bu basit ve masum görünümlü otomobilin arkasına saklandığını fark etmenize yardımcı olmaz. Dosyayı tarayan diğer çoğu kişi de ilk bakışta dosyayı göremez.

Türün ne olduğunu bilmiyorsanız, bu durum daha da kötüleştirilebilir, ancak ne olduğu hakkında yanlış bir varsayım yapan değişken adı seçersiniz, aslında 1a ile aynı sonucu elde etmek yerine, en baştan değil post-refactor.

  1. İlk yazarken kodu yazmak, programlamanın en çok zaman alan parçası değildir. Evet, otomatik olarak başlangıçta bazı kodların yazılmasını hızlandırır. Yasal uyarı olarak,> 100 WPM yazarım, bu yüzden belki de diğerleri kadar beni rahatsız etmiyor. Ama tek yapmam gereken bütün gün yeni kod yazmak olsaydı mutlu bir kampçı olurdum. Programlamanın en çok zaman alan kısmı, koddaki çoğaltılması zor, kenardan-küçük hataların teşhisidir; bu, genellikle belirgin olmayan açık sorunlardan kaynaklanır - örneğin, otomatik kullanımın aşırı kullanımı gibi (referans-kopya, imzalı, imzasız, int, bool, işaretçi vb.

Auto'nun standart kütüphane şablonu türleriyle korkunç bir sözdizimi için geçici bir çözüm olarak getirildiği bana açıkça görülüyor. İnsanların zaten aşina oldukları şablon sözdizimini düzeltmeye çalışmak yerine - ki, bozulabilecek varolan kodun tümü nedeniyle yapmak neredeyse imkansız olabilir - sorunu temelde gizleyen bir anahtar kelimeye ekleyin. Esasen "kesmek" olarak adlandırdığınız şey.

Aslında standart kütüphane konteynırları ile otomatik kullanımı konusunda herhangi bir anlaşmazlık yok. Anahtar kelimenin ne için yaratıldığı açıktır ve standart kütüphanedeki işlevlerin amaç olarak (veya bu konu için yazdığınız) temel olarak değişmesi muhtemel değildir, bu da otomatik olarak kullanımı güvenli hale getirir. Ancak, kendi kodunuzla ve çok daha değişken olabilecek ve potansiyel olarak daha temel değişikliklere tabi olabilecek arabirimlerle kullanma konusunda çok dikkatli olurdum.

Dilin kabiliyetini artıran bir diğer otomatik uygulama tipi ise agnostik makrolarda geçici değerler oluşturmaktır. Bu daha önce gerçekten yapamayacağın bir şey, ama şimdi yapabilirsin.


4
Başardın. Keşke bunu + 2 olarak verebilseydim.
cmaster

İyi bir "lanet olası dikkatli ol" - cevap. @cmaster: İşte.
Deduplicator

Bir tane daha kullanışlı durumda bulduk: auto something = std::make_shared<TypeWithLongName<SomeParam>>(a,b,c);. :-)
Notinlist 17:15

14

Evet, eğer kullanmazsanız değişken türünüzü bilmek kolaylaşır auto. Soru şudur: kodu okumak için değişkeninizin türünü bilmeniz gerekir mi? Bazen cevap evet olur, bazen hayır. Örneğin, bir yineleyici a alırken std::vector<int>, bunun bir std::vector<int>::iteratorveya auto iterator = ...;yeterli olduğunu bilmeniz gerekir mi? Herhangi birinin bir yineleyici ile yapmak isteyeceği her şey, yineleyici olduğu gerçeğiyle verilir - sadece türün ne olduğu önemli değildir.

Kullanım autookumak kodunuzu zorlaştırma ne zaman bu durumlarda.


12

Şahsen ben autosadece programcı için ne olduğu açıkça belli olduğunda kullanıyorum .

örnek 1

std::map <KeyClass, ValueClass> m;
// ...
auto I = m.find (something); // OK, find returns an iterator, everyone knows that

Örnek 2

MyClass myObj;
auto ret = myObj.FindRecord (something)// NOT OK, everyone needs to go and check what FindRecord returns

5
Bu, gerçekten otomatik olarak değil, kötü isimlendirmenin zarar görebilirliğin net bir örneğidir. Kimse "DoSomethingWeird" ın ne yaptığı konusunda en ufak bir fikre sahip değil. Her iki şekilde de belgeleri kontrol etmek zorunda kalacaksınız.
R. Martinho Fernandes,

4
Tamam, şimdi biraz daha iyi. Yine de değişkeni, hala acıtıyor olsa da, adlandırılmış buluyorum. auto record = myObj.FindRecord(something)Bunu yazman değişken türünün kayıt olduğu açıktı. Veya buna itbenzer isimler vermek bir yineleyici döndürdüğünü açıkça gösterir. Kullanmasanız bile auto, değişkeni doğru şekilde adlandırmanın , fonksiyonun herhangi bir yerindeki türe bakmak için bildirime geri dönmeniz gerekmeyeceği anlamına geldiğini unutmayın . Aşağıya oyumu kaldırdım, çünkü örnek şu an tam bir strawman değil, ancak hala argümanı burada satın almıyorum.
R. Martinho Fernandes,

2
@ R.MartinhoFernandes'e eklemek için: soru şudur: Şimdi tam olarak ne bir "kayıt" NE? Bunun bir kayıt olduğunu düşünüyorum, asıl temel ilkel tip başka bir soyutlama katmanıdır. Bu yüzden otomatik olmayan biri muhtemelen şöyle olurdu:MyClass::RecordTy record = myObj.FindRecord (something)
paul23

2
@ paul23: Eğer otomatik türüne karşı ne kullanıyorsanız, o zaman, tek itirazınız "bunu nasıl kullanacağımı bilmiyorum" ise, o zaman kazanırsınız. Her ikisi de yine de seni araştırıyor.
GManNickG

3
@GManNickG bana önemsizliğin tam tipini söyler.
paul23 19

10

Bu soru, programlayıcıdan programlayıcıya farklılık gösterecek olan görüşünü gerektirir, ancak hayır derdim. Aslında, çoğu durumda tam tersi, autoprogramcının minutiadan ziyade mantığa odaklanmasını sağlayarak kodun anlaşılmasını kolaylaştırabilir .

Bu, özellikle karmaşık şablon türleri karşısında geçerlidir. İşte basitleştirilmiş ve tartışmalı bir örnek. Hangisini anlamak daha kolay?

for( std::map<std::pair<Foo,Bar>, std::pair<Baz, Bot>, std::less<BazBot>>::const_iterator it = things_.begin(); it != things_.end(); ++it )

.. veya ...

for( auto it = things_.begin(); it != things_.end(); ++it )

Bazıları ikincisinin anlaşılmasının daha kolay olduğunu söyler, bazıları ise ilk söyler. Diğerleri ise, gereksiz bir kullanımın, autoonu kullanan programcıların düşmesine katkıda bulunabileceğini söyleyebilir , ama bu başka bir hikaye.


4
+1 Haha, herkes std::mapek olarak karmaşık şablon argümanları ile örnekler sunuyor .
Nawaz

1
@Nawaz: maps kullanarak çılgın uzun şablon adları ile gelip kolaydır . :)
John Dibling

@Nawaz: Ama neden hiç kimse döngülere dayalı olarak daha iyi ve daha okunaklı bir alternatif olarak kullanılmaya başladığını merak ediyorum ...
PlasmaHH

1
@PlazmaHH, yineleyicilerle olan tüm döngüler aralık esaslı olarak değiştirilemez, forörneğin yineleyiciler döngü gövdesinde geçersiz kılınmışsa ve önceden arttırılmaları veya hiç arttırılmaları gerekmiyorsa.
Jonathan Wakely

@PlasmaHH: Benim durumumda, MSVC10 döngüler için aralık tabanlı işlem yapmaz. MSVC10 benim C ++ 11 test cihazım olduğu için onlarla pek bir deneyimim yok.
John Dibling

8

Şimdiye kadar pek çok güzel cevap var, ancak asıl soruya odaklanmak için, autoHerb'ün liberal olarak kullanması için tavsiyesinde fazla ileri gittiğini düşünüyorum . Örneğiniz, kullanımın autoaçıkça okunabilirliğe zarar verdiği bir durumdur . Bazı insanlar bir değişkenin üzerine gelip türünü görebileceğiniz modern IDE'lerle ilgili bir sorun değil, ısrar ediyorum, ama aynı fikirde değilim: her zaman bir IDE kullanan insanlar bile bazen kod parçacıklarının izole edilmesine bakmalı (kod incelemelerini düşünün) , örneğin) ve bir IDE yardımcı olmaz.

Alt satır: autoyardımcı olduğunda kullanın : örn. Döngüler için yineleyiciler. Okuyucunun türünü bulmakta zorlandığı durumlarda kullanmayın.


6

Hiç kimsenin henüz net olmadığına dair otomatik olarak yardımcı olduğuna dikkat çekmemesine şaşırdım. Bu durumda, asıl kullanılabilir türü bulmak için bir şablonda #define veya typedef kullanarak bu sorunu çözersiniz (ve bu bazen önemsiz değildir) veya sadece auto komutunu kullanırsınız.

Platforma özgü tipte bir şey döndüren bir işleviniz olduğunu varsayalım:

#ifdef PLATFROM1
__int256 getStuff();
#else //PLATFORM2
__int128 getStuff();
#endif

Cadı kullanımı tercih eder misiniz?

#ifdef PLATFORM1
__int256 stuff = getStuff();
#else
__int128 stuff = getStuff();
#endif

ya da sadece basit

auto stuff = getStuff();

Tabii ki yazabilirsin.

#define StuffType (...)

bir yerlerde olduğu gibi

StuffType stuff = getStuff();

Aslında x'in türü hakkında daha fazla bir şey söyle? Oradan geri döndürülenin ne olduğunu söyler, ama tam olarak oto. Bu sadece gereksiz - 'şeyler' burada 3 kez yazılmıştır - bu bence 'otomatik' versiyonundan daha az okunabilir kılar.


5
Platforma özgü tipleri kullanmanın doğru yolu typedefonlar içindir.
cmaster

3

Okunabilirlik özneldir; duruma bakmak ve neyin en iyi olduğuna karar vermeniz gerekir.

Sizin de belirttiğiniz gibi, oto olmadan, uzun beyanlar çok fazla karışıklık yaratabilir. Ancak belirttiğiniz gibi, kısa bildirimler değerli olabilecek türdeki bilgileri kaldırabilir.

Bunun üzerine şunu da eklerdim: okunabilirliğe ve yazılabilirliğe değil baktığına emin ol. Yazması kolay olan kod genellikle okunması kolay değildir ve bunun tersi de geçerlidir. Mesela yazıyor olsaydım, otomatik olarak tercih ederim. Okuyor olsaydım, belki daha uzun açıklamaları.

Sonra tutarlılık var; bu senin için ne kadar önemli? Bazı parçalarda otomatik ve bazılarında açık beyanlar mı yoksa baştan beri tutarlı bir yöntem mi istiyorsunuz?


2

Daha az okunabilen kodun bir avantajı olacağım ve programcının onu daha fazla kullanması için teşvik edeceğim. Neden? Açıkçası, otomatik kullanan kodun okunması zorsa, o zaman yazmak da zor olacaktır. Programcı, işini daha iyi hale getirmek için anlamlı değişken adını kullanmaya zorlanır .
Belki başlangıçta, programcı anlamlı değişken isimlerini yazamayabilir. Ancak nihayetinde hataları düzeltirken ya da kod incelemesinde, kodu başkalarına açıklamak zorunda kaldığında ya da çok yakın olmayan bir zamanda, kodu bakım insanlarına açıklar, programcı hatayı gerçekleştirir ve kullanır. Gelecekteki anlamlı değişken adı.


2
En iyi ihtimalle, değişken isimleri yazılı kişiler gibi olsun istiyorum myComplexDerivedTypetip tekrarı (her yerde değişken kullanılır) tarafından kodu ve hangi ihmal insanları entices clutters eksik türü, telafi etmek için amaca adında değişkenin . Benim deneyimim, aktif olarak koda engel koymak kadar verimsiz bir şey olmaması.
cmaster

2

İki yönergem var:

  • Değişkenin türü açıksa, kullanımı otomatik olarak belirlemek zor veya yazmak zordur.

    auto range = 10.0f; // Obvious
    
    for (auto i = collection.cbegin(); i != cbegin(); ++i) // Tedious if collection type
    // is really long
    
    template <typename T> ... T t; auto result = t.get(); // Hard to determine as get()
    // might return various stuff
  • Belirli bir dönüşüme ihtiyacınız varsa veya sonuç türü belli değil ve karışıklığa neden olabilir.

    class B : A {}; A* foo = new B(); // 'Convert'
    
    class Factory { public: int foo(); float bar(); }; int f = foo(); // Not obvious

0

Evet. Ayrıntıları azaltır, ancak ortak yanlış anlama, detayların okunabilirliği azalttığıdır. Bu, yalnızca kodu girme yeteneğinizden ziyade okunabilirliğin estetik olduğunu düşünüyorsanız - bu, otomatik olarak artırılmaz. En sık alıntı yapılan örnekte, vektör yineleyiciler, otomatik kullanmanın kodunuzun okunabilirliğini arttırdığı yüzeyde görünebilir. Diğer yandan, otomatik anahtar kelimenin size ne vereceğini her zaman bilmiyorsunuz. Derleyicinin o içsel yeniden yapılanmayı yapmak için yaptığı gibi aynı mantıksal yolu izlemelisiniz ve özellikle yineleyicilerde yanlış varsayımlarda bulunacaksınız.

Günün sonunda 'auto', sözdizimsel ve estetik 'temizlik' için kod ve netliğin okunabilirliğini (bu sadece yineleyiciler gereksiz yere toplanmış sözdizimine sahip olduğu için gereklidir) ve verilen herhangi bir satırda 10 karakterden daha az karakter yazabilme yeteneğini feda eder. Bu riske veya uzun vadede dahil olan çabaya değmez.

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.