C ++ otomatik ve otomatik vs


91

Yerel değişkenler oluştururken kullanmak doğru mu (const) auto&yoksa auto?

Örneğin:

SomeClass object;
const auto result = object.SomeMethod();

veya const auto& result = object.SomeMethod();

SomeMethod () ilkel olmayan bir değer döndürür - belki başka bir kullanıcı tanımlı tür. Anladığım kadarıyla, const auto& resultSomeMethod () tarafından döndürülen sonuç, döndürülen tür için kopya yapıcısını çağıracağından , bu doğru. Yanlışım varsa lütfen düzelt.

Ya ilkel tipler için? const auto sum = 1 + 2;Doğru olduğunu varsayıyorum .

Bu, döngüler için aralık temelli için de geçerli mi?

for(const auto& object : objects)

1
Bunu okumanızı şiddetle tavsiye ederim: safaribooksonline.com/library/view/effective-modern-c/… İlk iki bölüm ücretsizdir ve şablon türü çıkarımını açıklar; bu, esasen nasıl autoçalıştığıdır ( initializer_lists'nin kendine özgü durumu hariç , bir şablon bağlamında çıkarılmamış), ardından autokesinti yazın.
vsoftco

Yanıtlar:


107

autove auto &&vakaların çoğunu kapsar:

  • autoYerel bir kopyaya ihtiyacınız olduğunda kullanın . Bu asla bir referans oluşturmaz. Kopyalama (veya taşıma) yapıcısı mevcut olmalıdır, ancak kopya elision optimizasyonu nedeniyle çağrılmayabilir .

  • auto &&Nesnenin yerel olup olmadığını umursamadığınızda kullanın . Teknik olarak, bu her zaman bir referans üretecektir, ancak eğer başlatıcı geçici ise (örneğin, fonksiyon değerle dönüyorsa), esasen kendi yerel nesneniz gibi davranacaktır.

    Ayrıca, auto &&nesnenin değiştirilebilir olacağını da garanti etmez. Bir constnesne veya referans verildiğinde , sonuç çıkarılacaktır const. Bununla birlikte, spesifik bağlam göz önüne alındığında, genellikle değiştirilebilirlik varsayılır.

auto &ve auto const &biraz daha spesifik:

  • auto &değişkeni başka bir şeyle paylaştığınızı garanti eder. Her zaman bir referanstır ve asla geçici değildir.

  • auto const &gibidir auto &&, ancak salt okunur erişim sağlar.

İlkel / ilkel olmayan türler için ne olacak?

Fark yok.

Bu, döngüler için aralık temelli için de geçerli mi?

Evet. Yukarıdaki ilkeleri uygulamak,

  • auto &&Döngü içindeki dizinin değerlerini değiştirme ve atma yeteneği için kullanın . (Yani, kapsayıcı gibi salt okunur bir görünüm sağlamadıkça, bu std::initializer_listdurumda etkin bir şekilde olacaktır auto const &.)
  • auto &Dizinin değerlerini anlamlı bir şekilde değiştirmek için kullanın .
  • Salt auto const &okunur erişim için kullanın .
  • auto(Değiştirilebilir) kopyalarla çalışmak için kullanın .

Ayrıca auto constreferans olmadan bahsediyorsunuz . Bu çalışır, ancak çok yaygın kullanılmaz çünkü zaten sahip olduğunuz bir şeye salt okunur erişimin nadiren bir avantajı vardır.


Sutter, auto & track constness diyor
Jesse Pepper

1
@JessePepper Evet. (Yine de otoriteye başvurmak biraz tuhaf.) Bunun belirli bir kısmından mı bahsediyorsunuz?
Potatoswatter

Özünde auto&iyi bir seçim gibi görünüyor. Ama const auto&zaten orada olmayan sabitliği eklemek istediğinizde kullanın. auto&&iletmek için, sanıyorum ki Sutter'ın düşündüğünden daha sık oluyor. Örneğin, auto&&hata ayıklama değerini görmek ve başka bir işleve geçirmek için std :: cout gibi bir dönüş değerini depolamak ve sonra bunu iki şeye "iletmek" isteyebilirsiniz. Auto &&'yi daha sık kullanırdım ama beklenmedik şeyler yaptığında bir veya iki kez ısırılmıştım. Keşke neyin yanlış gittiğine daha fazla dikkat etseydim!
Jesse Pepper

@JessePepper Evet, herhangi bir ifadenin daha küçük ifadelere bölünmesine izin vermesi gerekenauto&& eksik bir dil özelliğiyle ilgilidir . Eksik olan kısım ömür boyu uzama… Bunu düzeltmek için epeyce çaba sarf ettim ama kimse fark etmedi.
Punditry'ye

Otomatik sabitte: auto const x = fn () yazmak daha doğal olabilir; işlevin bir referans döndürmediğini biliyorsanız ve x nesnesinin hatalardan kaçınmak için değişmemesini veya kapsamda kullanıldığını belgelemesini istiyorsanız. Aynı şekilde normalde yazmazsınız: const int & x = 1; Ancak auto const & bu şekilde bildirilen referanslar için ömür boyu uzatma kuralları nedeniyle eşdeğer sonuçlar verir.
Spacen Jasset

47

Evet, yerel değişkenler için autove kullanımı doğrudur auto&. Bir fonksiyonun dönüş türünü alırken kullanmak da doğrudur auto&. Bu, döngüler için aralık temelli için de geçerlidir.

Genel kullanım kuralları autoşunlardır:

  • auto xKopyalarla ne zaman çalışmak istediğinizi seçin .
  • auto &xOrijinal öğelerle ne zaman çalışmak istediğinizi seçin ve bunları değiştirebilirsiniz.
  • Seç auto const &xözgün öğelerle çalışmak istiyoruz ve bunları değiştirmez zaman.

Sen oto belirtici hakkında daha fazla bilgi bulabilirsiniz burada .


10

autoşablon olarak tip kesinti aynı mekanizmayı, ben bundan çıkarılmaktadır ayracı-init listelerinin olmanın farkında olduğumu tek istisna kullanır autoolarak std::initializer_list, ancak bir şablon bağlamında olmayan çıkarılabilir.

auto x = expression;

önce sağ taraftaki ifadenin türünden tüm başvuru ve cv niteleyicilerini çıkararak, ardından türle eşleştirerek çalışır. Örneğin, varsa const int& f(){...}o zaman auto x = f();deduces xolarak intve değil const int& .

Diğer form,

auto& x = expression

şerit yok , yukarıdaki örneği kullanarak, bu yüzden, ev-eleme auto& x = f()deduces xolarak const int&. Diğer kombinasyonlar sadece cv niteleyicileri ekler.

Türünüzün her zaman cv-ref niteleyicileriyle çıkarılmasını istiyorsanız decltype(auto), decltypetür kesinti kurallarını kullanan C ++ 14'teki rezilliği kullanın .

Kısaca, eğer kopya istiyorsanız, kullanın auto, referans istiyorsanız kullanın auto&. constEk const-lik istediğinizde kullanın .


DÜZENLE Ek bir kullanım durumu vardır,

auto&& x = expression;

şablon kodundaki referansların iletilmesi durumunda olduğu gibi, referans daraltma kurallarını kullanır. Eğer expressionbir ldeğer ise, o zaman xcv-niteleyicileriyle bir lvalue referansıdır expression. Eğer expressionbir rvalue ise, o xzaman bir rvalue referansıdır.


@Potatoswatter Teşekkürler, düzenlendi. Aslında için özgeçmişi merak ediyorum rvalues. Test etmenin basit bir yolu var mı? Ve nasıl cv nitelikli bir değer elde edebilirsiniz? İşlev dönüşünde cv atılır.
vsoftco

Hayır, fonksiyon dönüşlerinde atılmaz. Tüm skaler türlerin prdeğerleri için atılır (C ++ 14 [ve diğer sürümler] §5 / 6). Bir işlev çağrısı veya dönüşüm gösterimi kullanarak bir tane alabilirsiniz. Cv nitelikli xvalues ​​her şey gibi çalışır: nadiren kullanılsalar da auto && x = std::move< const int >( 5 );bildirir int const && x.
Potatoswatter

@Potatoswatter teşekkürler, haklısın, benim hatam. İlk önce POD'larla test ettim, bu durumda cv atılır ve genel durumun bu olduğunu düşündüm. Elbette atılmaması gerekir, çünkü genel olarak cv'yi korumak isteyebilir (örneğin, rvalue dönüşlerinde const olmayan üye işlevi çağırılamaz).
vsoftco

Skaler türler için atıldı. POD'lar sınıflar olabilir. Her neyse, ifade modeli ile nesne modelinin kesişme noktasının kesik bir köşesi.
Potatoswatter

2

Yerel değişkenler oluştururken (const) auto & veya auto kullanmak doğru mu?

Evet. Auto, derleyici tarafından çıkarılmış bir türden başka bir şey değildir, bu nedenle normalde referansları kullanacağınız referansları ve normalde yerel kopyaları kullanacağınız yerel (otomatik) kopyaları kullanın. Bir referansın kullanılıp kullanılmayacağı tür kesintisinden bağımsızdır.

SomeMethod () ilkel olmayan bir değer döndürür - belki başka bir kullanıcı tanımlı tür. Anladığım kadarıyla const auto & result doğrudur, çünkü SomeMethod () tarafından döndürülen sonuç döndürülen tür için kopya yapıcısını çağıracaktır. Yanlışım varsa lütfen düzelt.

Yasal? Evet, kurucu ile. En iyi pratik? Muhtemelen hayır, hayır. En azından C ++ 11 ile değil. Özellikle, SomeMethod () 'dan döndürülen değer zaten geçiciyse. C ++ 11 hareket semantiği, kopya elizyonu ve dönüş değeri optimizasyonu hakkında bilgi edinmek isteyeceksiniz: https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always-pass-by- değer /

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199

https://isocpp.org/wiki/faq/ctors#return-by-value-optimization

Ya ilkel tipler için? Sabit otomatik toplamın = 1 + 2 olduğunu varsayıyorum; doğru.

Evet, bu güzel.

Bu, döngüler için aralık temelli için de geçerli mi?

for (const auto & object: nesneler)

Evet, bu da güzel. Bu tür bir kodu her zaman işte yazıyorum.

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.