C ++ 'da otomatik değişkenleri bildirmenin bir dezavantajı var mı?


143

Görünüşe göre auto, birçok yeni dili takip eden C ++ 11'e eklenmesi oldukça önemli bir özellikti. Python gibi bir dilde olduğu gibi, herhangi bir açık değişken bildirimi görmedim (Python standartlarını kullanarak mümkün olup olmadığından emin değilim).

autoDeğişkenleri açıkça belirtmek yerine bildirmek için kullanmanın bir dezavantajı var mı ?


1
Ayrıca bkz: stackoverflow.com/questions/6434971/… , stackoverflow.com/questions/15254461/… , stackoverflow.com/questions/6900459/… , stackoverflow.com/questions/8430053/is-c11-auto-type-dangerous ve belki de diğerleri. Bunların tam kopya olup olmadığından emin değilim, ama kesinlikle adaylar.
Cody Gray

3
Bulduğum tek dezavantajı, bir kod tabanını derleyicisi desteklemeyen (ve destekleme niyeti olmayan) bir (konsol) platformuna taşımak zorunda kaldığım zamandı!
Sam

7
Tam bütünlük için GotW # 94 "Neredeyse Her Zaman Otomatik": otlarutter.com/2013/08/12/…
Richard Critten

1
Ben cppcast dinliyordu ve çatışma b / w otomatik ve liste başlatıcılar bahsedildi. Bu podcast'i bulmaya çalışacağım.
Abhinav Gauniyal

2
bence ilk dezavantajı kodun okunabilirliğini etkiliyor
ggrr

Yanıtlar:


111

Sadece sakıncaları sordunuz, bu yüzden bunlardan bazılarını vurguluyorum. İyi kullanıldığında autoçeşitli avantajları da vardır. Dezavantajları kötüye kullanım kolaylığı ve kodun istenmeyen şekilde davranma potansiyelinin artmasından kaynaklanmaktadır.

Ana dezavantajı, kullanarak auto, yaratılan nesnenin türünü bilmemenizdir. Programcının derleyicinin bir türü çıkarmasını bekleyebileceği durumlar da vardır, ancak derleyici başka birini kesin olarak çıkarır.

Gibi bir beyan verildi

auto result = CallSomeFunction(x,y,z);

ne tür resultolduğu konusunda bilginiz olmayabilir . Bir olabilir int. Bir işaretçi olabilir. Başka bir şey olabilir. Bunların hepsi farklı operasyonları desteklemektedir. Kodu, gibi küçük bir değişiklikle önemli ölçüde değiştirebilirsiniz.

auto result = CallSomeFunction(a,y,z);

çünkü CallSomeFunction()sonuç türü için hangi aşırı yüklenmelere bağlı olarak tamamen farklı olabilir ve bu nedenle sonraki kodlar amaçlanandan tamamen farklı olabilir. Aniden daha sonraki kodda hata mesajlarını tetikleyebilirsiniz (örneğin, daha sonra int, artık bir şey değiştirmeye çalışmak, şu anda olan bir şeyi değiştirmeye çalışmak const). Daha sinsi değişiklik, değişikliğin derleyiciyi geçtiği yerdir, ancak sonraki kod farklı ve bilinmeyen - muhtemelen buggy - şekilde davranır.

Bu nedenle, bazı değişkenlerin türü hakkında net bilgi sahibi olmamak, kodun amaçlandığı şekilde çalıştığı iddiasını titizlikle haklı kılar. Bu, yüksek kritiklikteki (örneğin güvenlik açısından kritik veya görev açısından kritik) alanlarda "amaca uygunluk" iddialarını haklı çıkarmak için daha fazla çaba anlamına gelir.

Diğer, daha yaygın bir dezavantaj, bir programcının auto, kodun ne yaptığını düşünmek ve doğru yapmak için çalışmak yerine, kodu derlemeye zorlamak için künt bir araç olarak kullanması cazibesidir .


58
Bu tür örneklerin kullanımının dezavantajı varsa auto, o zaman ördek tipi dilin çoğunun tasarımda böyle bir dezavantaj yaşadığını belirtmek ilginçtir !
Leben Asa

11
Eğer CallSomeFunction()farklı bir türü, bağımsız değişkenler sekansına bağlı olarak geri döner, bu, bir tasarım bozukluk, CallSomeFunction()değil, bir sorun auto. Kullanmadan önce kullandığınız bir işlevin belgelerini okumazsanız, bu bir programcının hatasıdır, bir sorun değildir auto. - Ama burada şeytanın avukatı oynadığınızı anlıyorum, sadece Nir Friedman'ın çok daha iyi bir davası var.
DevSolar

16
@DevSolar: Neden T CallSomeFunction(T, int, int)bir tasarım hatası olsun? Açıkçası "argümanlarının sırasına bağlı olarak farklı bir tür döndürür."
MSalters

9
"En büyük dezavantajı, kullanarak auto, yaratılan nesnenin türünü bilmemenizdir." Bunun neden autoalt ifade geçişleriyle ilgili bir sorun değil, sorun olduğunu açıklayabilir misiniz ? Neden auto result = foo();kötü, ama foo().bar()değil?
Angew artık SO

24
Yorumlardan, "dezavantaj" ın bir şeyin kabul edilemez olmasının bir nedeni olarak yorumlandığı anlaşılıyor. Bir dil özelliğinin dezavantajı, geliştiricinin kabul etmeyi veya kabul etmemeyi - yani mühendislik ödünleşimi yapmayı - dikkate alması gereken bir dezavantajdır. Özelliğin neden kullanılması ya da kullanılmaması gerektiği hakkında kapsamlı iddialarda bulunmuyorum.
Peter

76

Bu autotam olarak ilkeli bir dezavantaj değil , ama pratikte bazıları için bir sorun gibi görünüyor. Temel olarak, bazı insanlar ya: a) autotipler için bir kurtarıcı olarak davranırlar ve kullanırken beyinlerini autokapatırlar veya b) her zaman değer türlerine neden olanları unuturlar . Bu insanların böyle şeyler yapmasına neden olur:

auto x = my_obj.method_that_returns_reference();

Hata! Bir nesneyi derinden kopyaladık. Genellikle bir hata ya da performans başarısız olur. Sonra başka şekilde de sallayabilirsiniz:

const auto& stuff = *func_that_returns_unique_ptr();

Şimdi sarkan bir referans alıyorsunuz. Bu sorunlardan hiç kaynaklanmıyor auto, bu yüzden onlara karşı meşru argümanlar olduğunu düşünmüyorum. Ama autobaşlangıçta listelediğim nedenlerle, bu sorunu (kişisel deneyimimden) daha yaygın yapıyor gibi görünüyor .

İnsanların işbölümünü ayarlayabilmeleri ve anlayabilmeleri için zaman verildiğini düşünüyorum: autoaltta yatan türü çıkarır, ancak yine de referanslık ve sabitlik hakkında düşünmek istersiniz. Ama biraz zaman alıyor.


Başlamak için pahalı bir nesneyi neden derin kopyalayabilirsiniz?
Laurent LA RIZZA

3
@LaurentLARIZZA: Bazı sınıflar, bazen ihtiyaç duyuldukları için (örneğin örnekleri std::vector) kopya yapıcılara sahiptir . Kopyalamak pahalı olmak bir sınıfın değil, tek tek nesnelerin bir özelliğidir. Bu nedenle method_that_returns_reference, bir kopya oluşturucuya sahip olan ancak kopyalanması oldukça pahalı olan (ve taşınamayan) bir sınıf nesnesine atıfta bulunabilir.
Marc van Leeuwen

@MarcvanLeeuwen: Nesnenin kopyalanması pahalıysa ve taşınamıyorsa, neden bir std::vector? (Çünkü olabilir, evet, ya da sınıfı kontrol etmediğiniz için, ama mesele bu değildir) Kopyalamak pahalıysa (ve kaynak olduğu için, kopyalanabilir olduğu için), neden nesne üzerinde COW kullanmıyorsunuz? Veri konumu zaten nesnenin büyüklüğü tarafından öldürülmüş.
Laurent LA RIZZA

2
@LaurentLARIZZA Bir vektörde depolanan bir şeyin pahalı olmasının bir örneği değil, sadece düzenli bir örneğin <çift> vektörünün kopyalanması pahalıdır, bir yığın tahsisi + O (N) çalışmasıdır. Hareket etmek kırmızı bir ringa balığıdır. Gösterdiğim ilk satır, döndürülen referans bir rvalue referansı olmadıkça hareket etmeyecek, kopyalanmayacak. İNEK gerçekten ne burada ne de oradadır. Gerçek şu ki, nesneleri kopyalamak her zaman var olacaktır.
Nir Friedman

4
@Yakk Bunu güvenli bir şekilde yapamaz, çünkü dilimleyebilir. Yapabileceği tek güvenli şey = deleteaşırı yüklenmedir. Daha genel olarak söylediğiniz şey bir çözüm olsa da. Bu, ilgilendiğinizde araştırdığım bir konudur: nirfriedman.com/2016/01/18/… .
Nir Friedman

51

Diğer cevaplar, "bir değişkenin türünün ne olduğunu gerçekten bilmiyorsunuz" gibi dezavantajlardan bahsediyor. Bunun büyük ölçüde koddaki özensiz adlandırma kuralıyla ilgili olduğunu söyleyebilirim. Arayüzleriniz açıkça adlandırılmışsa, tam türün ne olduğunu önemsemeniz gerekmez . Tabii, auto result = callSomeFunction(a, b);sana fazla bir şey söylemiyor. Ancak , tam türünün ne olduğunu umursamadan auto valid = isValid(xmlFile, schema);kullanmanız için yeterli olduğunu söyler valid. Sonuçta, sadece if (callSomeFunction(a, b)), türü de bilmezdiniz. Diğer alt ifade geçici nesneleri için de aynı şey geçerlidir. Bu yüzden bunun gerçek bir dezavantajı olduğunu düşünmüyorum auto.

Birincil dezavantajı, bazen, tam dönüş türünün çalışmak istediğiniz şey olmadığıdır . Aslında, gerçek dönüş türü bazen bir uygulama / optimizasyon ayrıntısı olarak "mantıksal" dönüş türünden farklıdır. İfade şablonları buna en iyi örnektir. Diyelim ki buna sahibiz:

SomeType operator* (const Matrix &lhs, const Vector &rhs);

Mantıken, biz beklenebilir SomeTypeolması Vectorve biz kesinlikle bizim kodunda gibi bunu tedavi etmek istiyorum. Ancak, optimizasyon amacıyla kullandığımız cebir kütüphanesinin ifade şablonlarını uygulaması mümkündür ve gerçek dönüş türü şöyledir:

MultExpression<Matrix, Vector> operator* (const Matrix &lhs, const Vector &rhs);

Şimdi, sorun büyük MultExpression<Matrix, Vector>olasılıkla a const Matrix&ve const Vector&dahili olarak depolanacak ; Vectortam ifadesinin bitiminden önce a'ya dönüşmesini bekler . Bu kod varsa, her şey yolunda:

extern Matrix a, b, c;
extern Vector v;

void compute()
{
  Vector res = a * (b * (c * v));
  // do something with res
}

Ancak, autoburada kullansaydık , başımız belaya girebilirdi:

void compute()
{
  auto res = a * (b * (c * v));
  // Oops! Now `res` is referring to temporaries (such as (c * v)) which no longer exist
}

3
@NirFriedman Haklısın güçlü, ama aslında bunun autoçok az dezavantajı olduğunu hissediyorum , bu yüzden bu güçte duruyorum. Proxy'lerin vb. Diğer örnekleri arasında çeşitli "dize oluşturucular" ve DSL'lerde bulunan benzer nesneler bulunur.
Angew artık

2
İfade şablonlarından ve daha autoönce, özellikle Eigen kütüphanesi tarafından ısırıldım . Bu özellikle zor çünkü sorun genellikle hata ayıklama yapılarında görünmez.
Dan

1
Kullanımı autokullanırken de ısırabilir Armadillo optimizasyon amacıyla şablon meta-programlama yoğun kullanımını gündeme getirmektedir matris kütüphanesi. Neyse ki geliştiriciler ile ilgili sorunları önlemek için kullanılabilecek .eval () işlevini auto
eklediler

2
"Arayüzleriniz açıkça adlandırılmışsa, tam türün ne olduğunu önemsemeniz gerekmez" Derleyiciniz değişkenlerin adlarını inceleyerek kodunuzun doğruluğunu kontrol edemez. Bu, bir yazı sisteminin tüm noktasıdır. Körü körüne atlamak aptalca!
Yörüngedeki Hafiflik Yarışları

1
@Angew: Geçiciler için bir sorun değil çünkü genellikle onları hemen kullanıyorsunuz, autogenellikle bir tür kontrol autoiçermiyor (ve her yere sıçramak bu tür güvenliği tıpkı diğer her yerde olduğu gibi ortadan kaldırıyor). İyi bir karşılaştırma değil.
Yörüngedeki Hafiflik Yarışları

13

Sakıncaları biri bazen beyan edemezler const_iteratorile auto. Bu sorudan alınan kodun bu örneğinde sıradan (const olmayan) yineleyici alacaksınız :

map<string,int> usa;
//...init usa
auto city_it = usa.find("New York");

3
iteratorHaritanızın olmadığı için her durumda bir an alırsınız const. bunu a biçimine dönüştürmek istiyorsanız const_iterator, değişken türünü her zamanki gibi açıkça belirtin veya haritanızın bağlamında sabit olması için bir yöntem ayıklayın find. (Ben ikincisini tercih ederim. SRP.)
Laurent LA RIZZA

auto city_it = static_cast<const auto&>(map).find("New York")? veya C ++ 17 ile auto city_if = std::as_const(map).find("New York").
Dev Null

11

Kodunuzu okumak biraz daha zor veya sıkıcı hale getirir. Böyle bir şey düşünün:

auto output = doSomethingWithData(variables);

Şimdi, çıktı türünü bulmak için doSomethingWithDataişlevin imzasını izlemeniz gerekir .


40
Her zaman değil. örneğin auto it = vec.begin();okumaktan çok daha kolay std::vector<std::wstring>::iterator it = vec.begin();.
Jonathan Potter

4
Kabul. Kullanım durumuna bağlıdır. Bu konuda daha kesin olabilirdim.
Skam

1
@SeeDart evet, böyle otomatik kullanan insanlar yanlış yapıyor.
lciamp

6
"İşlev imzasını takip edin", bu bir fare imleci veya tuşa basmak değilse ("sembolü takip et" / "bildirime git" / her ne denirse), düzenleyicinizi daha fazla yapılandırmanız veya bunu konfigürasyon olmadan yapabilen bir IDE'ye geçin ... Ancak puanınız hala geçerli.
hyde

6
Ben bir IDE içinde değil ama check-in incelerken diffs küçük gözetleme deliklerinde fark ettim! Otomatik ile bu nedenle okumak daha zordur.
JDługosz

10

Bu geliştirici gibi nefret ediyorum auto. Ya da daha doğrusu, insanların nasıl kötüye kullanıldığından nefret ediyorum auto.

Yazmayı azaltmak için değilauto , genel kod yazmanıza yardımcı olmak için (güçlü) görüşüm . C ++, geliştirme süresini en aza indirmek için değil , sağlam kod yazmanıza izin veren bir dildir . Bu, C ++ 'ın birçok özelliğinden oldukça açıktır, ancak maalesef bu gibi yeni olanlardan birkaçı, yazarak yanıltıcı insanları yazarak tembelleşmeleri gerektiğini düşünmeye indirgiyor.

auto

Önceki autogünlerde insanlar typedefs'yi kullandı , bu harikaydı çünkü typedef kütüphane tasarımcısı dönüş türünün ne olması gerektiğini anlamanıza yardımcı oldu, böylece kütüphane beklendiği gibi çalışıyor. Kullandığınızda auto, bu denetimi sınıfın tasarımcısından alırsınız ve bunun yerine derleyiciden türün ne olması gerektiğini anlamasını istersiniz , bu da araç kutusundan en güçlü C ++ araçlarından birini kaldırır ve kodlarını kırma riski taşır .

Kullanmak Genellikle, autoçünkü olması gerektiği kodunuzu için çalışan herhangi makul türü , değil bunu birlikte çalışması gerektiğini türünü yazmak için sadece çok tembel çünkü. autoTembellik için bir araç olarak kullanırsanız , o zaman ne olur, sonunda programınıza, genellikle kullandığınız için gerçekleşmeyen örtük dönüşümlerin neden olduğu ince hatalar uygulamaya başlamanızdır auto.

Ne yazık ki, bu hataların kısa bir örnekte gösterilmesi zordur, çünkü kısalığı onları bir kullanıcı projesinde ortaya çıkan gerçek örneklerden daha az ikna edici hale getirir - ancak, belirli örtük dönüşümlerin alınmasını bekleyen şablon ağırlıklı kodda kolayca ortaya çıkar yer.

Bir örnek istiyorsanız, burada bir tane var . Bununla birlikte, küçük bir not: kodu atlayıp eleştirmeye başlamadan önce: bu tür örtülü dönüşümler etrafında birçok tanınmış ve olgun kütüphanenin geliştirildiğini ve imkansız değilse zor olabilecek sorunları çözdükleri için orada olduklarını unutmayın. başka türlü çözmek. Eleştirmeden önce daha iyi bir çözüm bulmaya çalışın .


3
which was great because typedef allowed the designer of the library to help you figure out what the return type should be, so that their library works as expected. When you use auto, you take away that control from the class's designer and instead ask the compiler to figure out what the type should beIMO gerçekten iyi bir neden değil. Güncel IDE'ler, örneğin Visual Studio 2015, fareyle üzerine gelindiğinde değişkenin türünü kontrol etmenizi sağlar auto. Bu tam olarak * ile aynıdır typedef.
Sombrero Tavuk

@JameyD: Orada birkaç önemli noktayı kaçırıyorsunuz: (1) IDE argümanınız yalnızca tür somutsa, şablon değil, işe yarar. IDE'ler muhtemelen bağımlı türler için size doğru türü söyleyemez, örn typename std::iterator_traits<It>::value_type. (2) bütün nokta anlaşılmaktadır tip ihtiyaç oldu değil doğru tür önceki kod tasarımcı tarafından amaçlanan "aynı" olarak; kullanarak auto, tasarımcının doğru türü belirleme yeteneğini ortadan kaldırmış olursunuz.
user541686

Temel olarak, cevaplardan birinin daha önce bahsettiği vekillerden bahsediyorsunuz. İfade şablonları ve <bool> vektör saçmalık çoğu insan için günlük kod değildir. Çoğu durumda, sen yok örtük dönüşüm elde etmek istiyorsanız ve oto ile yardımcı olur. Herb Sutter, blog yayınlarından birinde otomobilin avantajlarından bahsediyor ve çoğunlukla tuş vuruşlarıyla ilgili değil, aynı zamanda sadece genel kod için de değil. Ayrıca, sağladığınız ilk bağlantı, blog yazısı sadece korkunç bir tavsiyedir (bu yüzden yorum bölümünde titizlikle eleştirilmiştir).
Nir Friedman

@NirFriedman: "... vector<bool>saçmalık" ... af? Sizce nasıl bitsetuygulanır? Yoksa bit kaplarının tamamen saçma olduğunu mu düşünüyorsunuz ?!
user541686

1
@NirFriedman: <bool> vektörü hakkında hiçbir şey benim için haber değil. Sana anlatmaya çalıştığım ve anlamayı açıkça reddettiğin şey, bu sorunun amaçları için bitset'in <bool> vektöründen farklı olmaması - her ikisinin de proxy kullanması, çünkü proxy'lerin yararlı olduğu kabul edildi ve vekillerin yararlı olması, inkarda yaşamak yerine kabul etmeniz gereken bir gerçektir. Proxy'lerin yararlı olup olmadığını düşünmek için bunu tartışmaya bırakabilir misiniz? Bu bir tartışma konusu değil ve aynı zamanda onlar hakkındaki düşünceniz sadece sizin fikrinizdir, bir tür gerçek değildir.
user541686

6

autokendi başına dezavantajları yoktur ve ben (el-dalgalı) yeni kod her yerde kullanmak için savunmak. Kodunuzun sürekli yazımını ve sessiz dilimlemeden kaçınmasını sağlar. (Eğer Btüretirse Ave Aaniden dönen bir işlev dönerse B, autodönüş değerini saklaması beklendiği gibi davranır)

Bununla birlikte, C ++ 11 öncesi eski kod, açıkça yazılan değişkenlerin kullanımından kaynaklanan örtük dönüşümlere dayanabilir. Açıkça yazılan bir değişkeni autodeğiştirmek, kod davranışını değiştirebilir , bu nedenle dikkatli olmanız daha iyi olur.


Aşağı oylama adil, ancak neden hakkında yorum yapabilir misiniz?
Laurent LA RIZZA

Seni küçümsemedim, ama autokendi başına dezavantajları var (ya da en azından - çoğu düşünüyor). Sutter, Alexandrescu ve Meyers ile bu panel tartışmasında ikinci soruda verilen örneği ele alalım : Eğer varsa auto x = foo(); if (x) { bar(); } else { baz(); }ve foo()geri dönerseniz - bir enum döndürmek için değişiklikler boolyapılırsa ne olur foo()(iki yerine üç seçenek)? autoKod çalışmalarına devam eder, ancak beklenmedik sonuçlar üretecektir.
einpoklum

@einpoklum: İşlenmemiş bir numaralandırma durumunda kullanmak boolyerine autoherhangi bir şey değiştiriyor mu? Yanılıyor olabilirim (burada kontrol edemiyorum), ama bence tek fark dönüşümün booldurumdaki durumun değerlendirilmesi yerine değişken bildirimde gerçekleşmesidir if. Eğer enumkapsamı belirtilirse, dönüşüm boolaçık bir bildirim yapılmadan gerçekleşmeyecektir.
Laurent LA RIZZA

4

Anahtar kelime autotürü dönüş değerinden çıkarır. Bu nedenle, bir Python nesnesiyle eşdeğer değildir, örn.

# Python
a
a = 10       # OK
a = "10"     # OK
a = ClassA() # OK

// C++
auto a;      // Unable to deduce variable a
auto a = 10; // OK
a = "10";    // Value of const char* can't be assigned to int
a = ClassA{} // Value of ClassA can't be assigned to int
a = 10.0;    // OK, implicit casting warning

Yana autoderleme sırasında çıkarılır, bu çalışma zamanı olursa olsun herhangi bir dezavantajı var olmayacaktır.


1
evet, temelde type()python ne yapar. Türü çıkarır, bu türden yeni bir değişken oluşturmaz.
lciamp

2
@lciamp Aslında, bu olurdu decltype. autoözellikle değişken atama içindir.
Kübik

4

Bana şimdiye kadar burada kimsenin bahsetmediği, ama kendisi için bir cevap vermeye değer.

(Herkes bunu bilmeli olsa bile C != C++) C ile yazılmış kod C ++ kodu için bir taban sağlamak üzere kolayca tasarlanabildiğinden ve bu nedenle C ++ uyumlu olmak için fazla çaba harcamadan tasarlanabildiğinden, bu tasarım için bir gereklilik olabilir.

Bazı iyi tanımlanmış yapıları Cgeçersiz C++ve tersi bazı kuralları biliyorum . Ancak bu sadece yürütülebilir dosyalar ile sonuçlanır ve çoğu zaman çökmelere neden olan garip döngülerle fark edilen (veya fark edilmeden kalabilir, ancak burada önemli olmayan) bilinen UB cümlesi geçerlidir.

Ama autoilk kez 1 Bu değişiklikler!

Daha autoönce depolama sınıfı belirleyicisi olarak kullandığınızı ve kodu aktardığınızı düşünün . (Kullanılma biçimine bağlı olarak) zorunlu olarak “kırılmaya”; aslında programın davranışını sessizce değiştirebilir.

Bu akılda tutulması gereken bir şey.


1 En azından ilk kez farkındayım.


1
Derlemeye çalışırken yine de derleyici hatası alıyorsunuz.
Sombrero Tavuk

@JameyD: Ne yapardı? neden farklı anlamlarda 2 geçerli kod durumu hiç hata yapmalı?
dhein

8
intC "hiçbir tür ima " güveniyorsanız, bundan alacak tüm kötü şeyler hak. Ve buna güvenmiyorsanız, bir türün yanındaauto bir depolama sınıfı belirteci olarak kullanmak , C ++ 'da güzel bir derleme hatası verecektir (bu durumda İyi Bir Şey).
Angew artık SO

1
@Yani bahsettiğim durum bu, evet. Bunu ben yapmıyorum. Ama en azından akılda tutulması gereken bir şey.
dhein

3

Düşünebilmemin bir nedeni, geri dönen sınıfı zorlama fırsatını kaybetmenizdir. İşleviniz veya yönteminiz uzun bir 64 bit döndürdüyse ve yalnızca 32 imzasız int istediyseniz, bunu kontrol etme fırsatını kaybedersiniz.


1
Static_cast ve IIRC var, örneğin Meyers 'Effective Modern C ++, otomatik yazılan değişken için tür belirtmek için bile kullanmanızı önerir.
hyde

2

Bu cevapta tarif ettiğim autogibi bazen istemediğiniz korkak durumlarla sonuçlanabilir. auto&Sadece autobir işaretçi türü oluşturabilirsiniz yaparken açıkça bir referans türü olduğunu söylemek gerekir . Bu, belirleyiciyi hep birlikte atlayarak karışıklığa neden olabilir ve gerçek bir referans yerine referansın bir kopyasına neden olabilir.


2
Bu korkak değil. Ne autoreferansı ne de consttürü çıkartıyor . autoReferans olması için kullanmanız daha iyi olur auto&&. (evrensel referans) Türün kopyalanması ucuz değilse veya bir kaynağa sahipse, türün başlangıç ​​için kopyalanmaması gerekir.
Laurent LA RIZZA

1

Diğer rahatsız edici bir örnek:

for (auto i = 0; i < s.size(); ++i)

imzalı bir int olduğu için bir uyarı ( comparison between signed and unsigned integer expressions [-Wsign-compare]) oluşturur i. Bundan kaçınmak için örn.

for (auto i = 0U; i < s.size(); ++i)

veya belki de daha iyisi:

for (auto i = 0ULL; i < s.size(); ++i)

1
Evet bunu da rahatsız edici buluyorum. Ancak dilde delik başka bir yerde. Bu kodun gerçekten taşınabilir olabilmesi için, sizegeri dönüşleri varsayarak size_t, size_tgerçek bir kelimeye sahip olmanız gerekir 0z. Ancak bunu yapmak için bir UDL bildirebilirsiniz. ( size_t operator""_z(...))
Laurent LA RIZZA

1
Tamamen teorik itirazlar: ana akım mimarilerin unsignedtüm değerlerini tutacak kadar büyük olması muhtemel değildir std::size_t, bu nedenle birisinin saçma devasa sayıda elemente sahip bir kabı olması olası olmayan kullanım unsigned, daha düşük aralıkta sonsuz bir döngüye neden olabilir endeksleri. Bunun bir sorun olması muhtemel olmasa da, std::size_tniyeti doğru bir şekilde gösteren temiz kod almak için kullanılmalıdır. unsigned long longUygulamada muhtemelen aynı olması gerekse de , kesinlikle yeterli olacağından emin değilim .
underscore_d

@underscore_d: evet, adil nokta - unsigned long longen az 64 bit olması garanti edilir, ancak teoride size_tbundan daha büyük olabilir. Tabii ki konteynırınızda> 2 ^ 64 elementiniz varsa, endişelenmeniz gereken daha büyük sorunlarınız olabilir ... ;-)
Paul R

1

autoOkuyucunun türünü kolayca ve açık bir şekilde düşürebileceği veya türünün bir yorumu veya gerçek türü çıkaran bir adla iyi belgelendirildiği yerelleştirilmiş bir bağlamda kullanıldığında iyi olduğunu düşünüyorum . Nasıl çalıştığını anlamayanlar, onu yanlış şekillerde kullanabilirler, örneğin yerine templateveya benzeri gibi. Bence bazı iyi ve kötü kullanım durumları.

void test (const int & a)
{
    // b is not const
    // b is not a reference

    auto b = a;

    // b type is decided by the compiler based on value of a
    // a is int
}

İyi Kullanımlar

yineleyiciler

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int> v();

..

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int>::iterator it = v.begin();

// VS

auto vi = v.begin();

İşlev İşaretçileri

int test (ClassWithLongName1 a, ClassWithLongName2 b, int c)
{
    ..
}

..

int (*fp)(ClassWithLongName1, ClassWithLongName2, int) = test;

// VS

auto *f = test;

Kötü Kullanımlar

Veri akışı

auto input = "";

..

auto output = test(input);

İşlev İmzası

auto test (auto a, auto b, auto c)
{
    ..
}

Önemsiz Durumlar

for(auto i = 0; i < 100; i++)
{
    ..
}

İstediğiniz zaman, isterseniz bir intkarakter daha yazmanız gerekir auto. Bu kabul edilemez
Rerito

@Rerito evet, intburada kolayca görülebiliyor ve yazım intdaha kısa. Bu yüzden önemsiz bir durum.
Khaled.K

0

Kimsenin bundan bahsetmediğine şaşırdım, ancak bir şeyin faktöriyelini hesapladığınızı varsayalım:

#include <iostream>
using namespace std;

int main() {
    auto n = 40;
    auto factorial = 1;

    for(int i = 1; i <=n; ++i)
    {
        factorial *= i;
    }

    cout << "Factorial of " << n << " = " << factorial <<endl;   
    cout << "Size of factorial: " << sizeof(factorial) << endl; 
    return 0;
}

Bu kod şu çıktıyı verecektir:

Factorial of 40 = 0
Size of factorial: 4

Bu kesinlikle beklenen sonuç değildi. Bu auto, değişken faktörünün türüne intatandığı gibi çıkarıldığı için oldu 1.

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.