C ++ 11'e geçiş nasıl yapılır?


35

Bir süredir C ++ 'da programlama yapıyorum, fakat çoğunlukla C ++' ın düşük seviyeli özelliklerine odaklanmıştı. Bununla, çoğunlukla işaretçilerle ve ham dizilerle çalışmaktan bahsediyorum. Bence bu davranış, C ++ 'ı C ile sınıf olarak kullanmak olarak bilinir. Buna rağmen, C'yi sadece yakın zamanda ilk defa denedim. C # ve Java gibi dillerin bu sözlükleri Sözlükler ve Listeler gibi uygun standart kütüphane sınıflarında nasıl sakladıklarına çok şaşırdım.

C ++ standart kütüphanesinin vektörler, haritalar ve dizgiler gibi birçok kapsayıcıya sahip olduğunu ve C ++ 11'in yalnızca std :: array ve aralıklı döngüler ekleyerek buna eklediğini biliyorum.

Bu modern dil özelliklerinden ve hangilerinin hangi anlara uygun olduğunu kullanmayı en iyi nasıl öğrenebilirim? Bugünlerde C ++ 'da yazılım mühendisliğinin çoğunlukla manuel bellek yönetimi bulunmadığı doğru mu?

Son olarak, yeni standardın tadını çıkarmak için hangi derleyiciyi kullanmalıyım? Visual Studio'nun mükemmel hata ayıklama araçları var, ancak VS2012'nin bile korkunç C ++ 11 desteği var.


2
VS2012'nin C ++ 11 desteğini "korkunç" olarak adlandırmanın biraz abartılı olduğunu söyleyebilirim ama kesinlikle daha iyi olabilirdi (başlatıcı listelerinin eksik olması test / oyuncak kodu için özellikle can sıkıcıdır). Ancak, derleyici güncellemelerini VS'nin geri kalanından bağımsız olarak göndereceklerini açıkladıklarını unutmayın, bu nedenle 2013 yılında VS2012'de birkaç C ++ 11 özelliği beklediğimizi tahmin ediyorum.
Martin Ba

3
İlk başta C ++ 11'i öğrenmek için bunu önermek garip olurdu, ama yine de C-Sınıfları topraklarında sıkışıp kaldığınızı görmek ... On yıl önce Koenig / Moo'nun Hızlandırılmış C ++' ını okudum . Zaten ben zaten şablon meta-programlama yapıyordum (sadece bir inceleme için okudum), ama yine de bir vahiy gibi hissettim. (O zamandan beri C ++ öğretmek için bir üs olarak kullandım.) C'den gelince , kitap size emrinizde olduğunu bilmediğiniz yepyeni bir dili gösterebilir. Sadece 250 sayfa ve hızlı bir şekilde C ++ 11'e özgü bir şeye ilerleyebilirsiniz, ancak IMO bu değerli bir adımdır.
sbi

4
g++ -std=c++11
fredoverflow

Yanıtlar:


50

İlk olarak, bazı kurallar:

  • std::unique_ptrGenel gider akıllı işaretçisi olarak kullanın . Ham işaretçilerle bu kadar sık ​​uğraşmanıza gerek yok. std::shared_ptrAynı şekilde çoğu durumda gereksizdir. Paylaşılan mülkiyet isteği, genellikle ilk başta mülkiyet konusunda düşünce eksikliğine ihanet eder.

  • Kullanım std::arraystatik uzunlukta diziler için ve std::vectordinamik için.

  • Genel olarak genel algoritmalar kullanın, özellikle:

    • <algorithm>
    • <numeric>
    • <iterator>
    • <functional>
  • Kullanılabilirliği autove decltype()nerelerde okunabilirlik kullandığını kullanın . Özellikle, bir şeyi bildirmek istediğinizde, ancak yineleyici veya karmaşık şablon türü gibi umursamadığınız bir tür belirtmek istediğinizde kullanın auto. Bir şeyi başka bir şeyin türü olarak bildirmek istediğinizde, kullanın decltype().

  • Yapabildiğiniz zaman işleri güvenli hale getirin. Değişmezleri belirli bir konuda zorlayan iddialara sahipseniz, bu mantık bir tipte merkezileştirilebilir. Ve bu mutlaka herhangi bir çalışma zamanı ek yükü sağlamaz. Ayrıca (T)xdaha açık (ve aranabilir!) Lehine C tarzı atmalardan ( ) kaçınılması gerektiğini söylemeden geçmelidir static_cast.

  • Son olarak, üçün kuralının nasıl olduğunu bilin:

    • çöp yakma fırını
    • Yapıcıyı kopyala
    • Atama operatörü

    Hareket yapıcı ve hareket atama operatörünün eklenmesiyle beş kural olmuştur. Ve genel olarak referans referanslarını ve kopyalamanın nasıl önleneceğini anlayın.

En iyi nasıl kullanılacağını karakterize edilmesi zor bu yüzden C ++, karmaşık bir dildir tüm o. Ancak, iyi C ++ geliştirme uygulamaları C ++ 11 ile temelde değişmedi. Manuel olarak yönetilen bellek yönetimi yerine hala bellek yönetimli kapları tercih etmelisiniz; akıllı işaretçiler bunu verimli bir şekilde yapmayı kolaylaştırır.

Modern C ++ 'nın gerçekten manuel bellek yönetiminden arınmış olduğunu söyleyebilirim; C ++' ın bellek modelinin avantajı , onun manuel olması değil, deterministik olmasıdır. Öngörülebilir ayrılmalar daha öngörülebilir performans sağlar.

Bir derleyiciye gelince, G ++ ve Clang, C ++ 11 özellikleri açısından rekabetçi ve eksikliklerini hızla tespit ediyorlar. Visual Studio kullanmıyorum, bu yüzden ne için ne de buna karşı konuşabiliyorum.

Son olarak, hakkında bir not std::for_each: genel olarak kaçının.

transform, accumulateVe erase- remove_ifişlevsel eski iyidir map, foldve filter. Ancak for_eachdaha genel ve bu nedenle daha az anlamlı - döngüden başka bir niyet ifade etmiyor . Bunun yanında, menzil bazlı olduğu gibi aynı durumlarda kullanılır forve noktasuz kullanıldığında bile sözdizimsel olarak daha ağırdır. Düşünmek:

for (const auto i : container)
    std::cout << i << '\n';

std::for_each(container.begin(), container.end(), [](int i) {
    std::cout << i << '\n';
});

for (const auto i : container)
    frobnicate(i);

std::for_each(container.begin(), container.end(), frobnicate);

6
Bu kurallara bazı bağlayıcı ilkeler var mı? Güzel bir öneri listesi gibi gözüküyor, ama ... Bu soruya Google üzerinden gelen bir yabancı olarak, cevabınız C ++ 11'i ilkeli bir şekilde seçmeme ve kendimi C ++ aksının etrafına sarmadan kullanmama nasıl yardımcı oluyor? ?
Robert Harvey

3
Liste için +1, ancak küçük bir nitpick'im var: ne zaman (haklı olarak) bir uyarı alırsam std::for_each, döngüyü temel alan düzlükten daha iyi bir yedek olarak beklerdim for.
Fabio Fracassi

@ FabioFracassi: Hata! Menzile dayalıstd::for_each değil, zıtlıktan anlaşılır şekilde yazdım . Karışıklığı önlemek için kaldırdım.
Jon Purdy

1
Olmazsa güncelleme yapardım std::for_each(). Lambda'nız olduğunda kesinlikle geleneksel bir fordöngüden iyidir . forDurum tabanlı olmayan bir döngü ile durum olmayabilir, ancak "aralık tabanlı fordöngü" yazmadınız.
sbi

@sbi: Aklımda, “ fordöngü” terimi “menzil tabanlı fordöngü” yi içeriyor . Daha fazla açıklama ve açıklığa kavuşturulması gereken bir örnek ile düzenleme yaptım, teşekkür ederim.
Jon Purdy

12

Başlangıç ​​noktası olarak:

  • char*Dizeler için kullanmayı bırak . Kullanın std::stringveya std::wstringve yalnızca kodunuzun daha kısa, daha okunaklı ve daha güvenli hale gelmesini izleyin
  • C tarzı dizileri (bildirilenler [ ]) kullanmayı std::vectorve diğer uygun konteyner sınıflarını kullanmayı bırakın . İşin güzel yanı std::vector, kendi uzunluğunu bilmesi, kapsam dışına çıktığında içeriğini temizlemesi, yinelenmesi kolaydır ve daha fazla öğe eklediğinizde kendisini daha büyük yapar. Ancak durumunuz için daha iyi çalışabilecek başka koleksiyonlar var.
  • Kullan std::unique_ptr- ve std::movehemen öğren . Bu bazı noncopyable nesneler neden olabileceğinden, tembellik bazen sizi doğru gönderebilir std::shared_ptr- ve bazı gerçek kullanım durumları olabilir std::shared_ptryanı
  • autoDaha önceki bildirimlere bağlı yineleyiciler ve türleri bildirirken kullanın (örneğin, daha önce bir şey vektörünü ilan ettiyseniz, şimdi bir şey bildirirsiniz, kullanın auto)
  • Algoritmaları ve for_each"ham" kelimesini, ne zaman olursa olsun, başka bir deyişle, tüm koleksiyonunuzu yinelemekte olduğunuz sonucuna varmak için döngü'nü dikkatli bir şekilde okumasını engellediğinizden emin olun for_each. Gibi önemsiz algoritma aramaları öğrenin iota, generate, accumulate, find_ifvb.
  • Lambdaları kullanın - algoritmalardan yararlanmanın kolay yoludur. Ayrıca kapıyı çok daha fazla açıyorlar.

Hangi derleyicinin kullanılacağı konusunda fazla uğraşmayın. VS2012'deki "korkunç, berbat" C ++ 11 desteğinin olmaması, variadic şablonların olmaması (evet, tam olarak variadic şablonlar kullanmak üzereydiniz ) ve {}başlatıcı orada olmamasıdır. Bunu da istiyorum ama üzerinde faydalı bir geliştirme aracı kullanmayı bırakmayacağım.

Yapılması gereken ikinci şey, kucakladıktan sonra std::, RAII düşünmeye başlamaktır. Ne zaman istersen

  • başlangıç ​​işlemi
  • eyleme başladığınız bir şeyle başlayan eylemler dizisi
  • İstisnalar durumunda bile yapılması gereken temizlik işlemleri

Öyleyse sahip olduğunuz şey bir yapıcı, çok sayıda üye işlevi ve bir yıkıcı. Sizin için bununla ilgilenen bir sınıf yazın. Rektörü ve dtoru bile yazman gerekmeyebilir. shared_ptrBir sınıfın üye değişkeni olarak koymak bir RAII örneğidir - bellek yönetimi kodunu yazmazsınız, ancak örneğiniz kapsam dışında kaldığında doğru şeyler olur. Dosyaların kapatılması, kilitlerin açılması, kilitler vb. Gibi şeylerin ele alınmasının, gözünüzün önünden daha basit ve daha küçük hale geleceğini (sızıntıları önlerken) genişletin.

Kendinden emin hissediyorsan, printflehine temizle cout, makrolardan ( #defineşeyler) kurtul ve PIMPL gibi bazı "gelişmiş deyimler" öğrenmeye başla. Pluralsight'ta bununla ilgili ücretsiz bir kurgu kullanarak izleyebileceğiniz bütün bir kursum var.


2
Yakında herhangi bir zamanda variadic şablonları kullanmama konusunda onun alaycılığını sevdim, ancak üniforma başlatmanın eksik olmasının günlük programlama için gerçekten önemli bir şeyi kaçırdığını düşünüyorum.
sbi

İlkleyici listeleri için sabırsızlanıyorum ... ne zaman alacağımızı öğrenmek için bekliyorum ...
Kate Gregory

VS2012'deki bir başka önemli eksiklik "v3 değer referansları", yani otomatik olarak oluşturulan hareket yapıcısı ve hareket atamasıdır .
Bay C64

3

Bu modern dil özelliklerinden ve hangilerinin hangi anlara uygun olduğunu kullanmayı en iyi nasıl öğrenebilirim?

Programlayarak. Tecrübe, öğrenmenin en iyi yoludur.

C ++ 11 birçok yeni özelliğe sahiptir (otomatik, değer, yeni akıllı işaretçiler - sadece birkaçını belirtmek için). En iyi başlangıç, onları kullanmaya başlamak ve ne zaman ve ne zaman ilginç bir makale bulduğunuzda onları okumaktır.

Bugünlerde C ++ 'da yazılım mühendisliğinin çoğunlukla manuel bellek yönetimi bulunmadığı doğru mu?

Bu yapmanız gerekenlere bağlıdır. Çoğu uygulama akıllı işaretçilerden kurtulabilir ve bellek yönetimini unutabilir. Kolayca kaçamayan uygulamalar var (örneğin, herhangi bir nedenden ötürü yeni yerleştirmeye veya özel bir bellek ayırıcıya ihtiyaç duyarlarsa).

Qt kullanmanız gerekiyorsa, kurallarını hafıza yönetimi için kullanmanız gerekir.

Yeni standardın tadını çıkarmak için hangi derleyiciyi kullanmalıyım?

En son standardı destekleyen elinizde ne varsa:

ancak hiçbir derleyici tüm özellikleri desteklemez.


-7

Üniversitem hala eğitim için C ++ kullanıyor. C ++ ile 5 senedir program yapıyorum ve şimdi yüksek lisans öğrencisiyim. Tabii ki, şimdi çok fazla Java, Ruby vs. kullanıyorum. Java gibi dilde bu özellikler konusunda acele etmemenizi gerçekten tavsiye ediyorum. Tecrübelerime ve görüşüme göre, C ++ 'ın düşük seviyeli özelliklerinden sonra. Şablon sınıfı, şablon fonksiyonları, operatörün üzerine yazdığı, sanal yöntemler, akıllı işaretçiler gibi C / C ++ ile genel programlama gibi konulara bakmalısınız. Nesneye Yönelik Tasarım Bölümü için, C ++ 'ın sahip olduğu ve Java'nın sahip olmadığı çoklu kalıtım gibi birçok özelliği vardır. Kalıtım güçlü ama aynı zamanda tehlikelidir. C ++ 'da nesne yönelimli tasarımın uygulama düzeyi de iyi bir konudur. İşlemler arası iletişim, iş parçacığı, C ++ 'da da önemlidir.

Derleyici ve hata ayıklayıcı için. Görsel stüdyonun harika olduğunu biliyorum. Ancak GDB, Valgrind ve Make Still'i öğrenmenizi ve bu araçlarda iyi olmanızı gerçekten tavsiye ederim. Microsoft harika, ama sizin için çok şey yaptı. Bir öğrenci olarak, Microsoft'un da sizin yaptığı şeyleri gerçekten öğrenmeniz gerekir. Derleyici için G ++ GNU’dan iyidir.

Sonuçta, yıllar sonra, gerçekten hissediyorum, en önemli şeyler raw dizisi gibi düşük seviye özelliklerdir. Vektör gerçekten sadece dinamik bir dizi. Bunlar benim önerilerim, belki de öznel bir şey, doğru olduğunu düşündüğün şeyi al.


6
Bu soruya nasıl cevap veriyor? Soru genel olarak C ++ öğrenmekle ilgili değil, C ++ 11'e geçmekle ilgili.
Roc Martí
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.