C ++ 'da en kötü uygulamalar, yaygın hatalar [kapalı]


35

Bu ünlü rantı Linus Torvalds tarafından okuduktan sonra , C ++ 'da programcıların tüm tuzaklarının neler olduğunu merak ettim. Açıkça bu soru ve cevaplarında ele alınan tipo ya da kötü program akışına değil, derleyici tarafından tespit edilemeyen ve ilk çalıştırmada açık hatalara neden olmayan daha yüksek seviyeli hatalara atıfta bulunmadım. C’de imkansız olan ancak kodlarının tam anlamıyla anlamadığını anlayan yeni gelenler tarafından C ++ 'da yapılması muhtemel şeyler.

Ayrıca, genellikle beklenmeyeceği büyük bir performans düşüşüne işaret eden cevapları da memnuniyetle karşılıyorum. Profesörlerimden birinin bir keresinde bana yazdığım bir LR (1) ayrıştırma üreteci hakkında söylediklerinin bir örneği:

Çok fazla gereksiz miras ve sanallık örneği kullandınız. Kalıtım, tasarımı çok daha karmaşık hale getirir (ve RTTI (çalışma zamanı türü çıkarım) alt sistemi nedeniyle verimsizdir) ve bu nedenle yalnızca ayrıştırma tablosundaki eylemler için mantıklı olduğu yerlerde kullanılmalıdır. Şablonları yoğun bir şekilde kullandığınız için pratik olarak mirasa ihtiyacınız yok. "


6
C / C ++ 'ta yapabileceğiniz daha kötü hataların bazıları çoğunlukla C mirasından kaynaklanıyor ... tanımsız davranışları, manuel hafıza yönetimini vb. Okuyun. Ayrıca, prof'in tavsiyesi sahte / yanlış görünüyor (bana kim gelmiyor bir C ++ uzmanı) - şablon hazırlığı, virtualişlevler için vtable ile normal bir sınıf vermelidir , değil mi?

8
Ya profesörünüzün söylediklerini yanlış hatırlıyorsunuz ya da ne dediği hakkında hiçbir fikri yoktu. Türetilmiş sınıfların genellikle işleri aramak için RTTI (AKA yansıması) kullanmaları gerekmez. Sanal yöntemler kullanıyorlarsa, kodun gönderme için boş bir arama yapması gerekebilir, ancak bu, birçok işlemcide tek bir ASM komutuna dönüşür. Önbellekleme sorunları nedeniyle işleri belirli bir miktarda yavaşlatabilir, ancak en zorlu kullanım durumlarının haricinde ek yükü hiç fark etmemeniz olasıdır. C ++ 'dan uzak durmak için birçok iyi neden var, ancak sağlam aramalar bunlardan biri değil.
Mason Wheeler

5
@FelixDombek: Genel olarak çok genel bir şekilde belirtilmiş ve yönetim kuruluna uygulanmış, profesörünüzden gelen alıntı büyük bir cehalet olduğunu gösteriyor. Tasarımınız bir tür çalışma zamanı polimorfizmine ihtiyaç duyduğunda , sanal işlevleri kullanmak genellikle en iyi seçimdir; İhtiyacınız olmadığında, kullanmayın: Örneğin türetilmiş sınıfları kullandığınız için sanal olmak için tüm yöntemlere ihtiyacınız yoktur.
Fred Nurk

5
@Mason Wheeler: RTTI, bir başarının dynamic_castbaşarılı olup olmayacağını belirleyebilecek kadar az ve diğer şeyleri belirleyebilecek türde bilgiler içeriyor , ancak yansıma üye özellikleri veya işlevler hakkında bilgi alamama dahil olmak üzere çok daha fazlasını kapsıyor. C ++ 'da mevcut.
David Rodríguez -

5
Kalıtım ve sanal fonksiyonlar büyük bir performans kazancı olmadığından profesörün yorumu biraz aldatıcıdır. Kalıtımın çok az kullanılması tavsiye, iyidir, ancak verimlilikten ziyade programın yapılışı sorunudur. Kalıtım, özellikle de korunan üyelerle, alacağınız kadar yakın bir ilişkidir ve eğer ihtiyacınız yoksa kullanmamalısınız.
David Thornley

Yanıtlar:


69

Torvalds burada kıçından çıkıyor.


Tamam, neden kıçından çıkıyor?

Her şeyden önce, onun rant gerçekten bir şey değil ama rant. Burada çok az gerçek içerik var. Bunun gerçekten ünlü ve hatta saygı duyulmasının tek nedeni, Linux Tanrısı tarafından yapılmış olmasıdır. Temel argümanı, C ++ 'nın boktan olduğu ve C ++' ı kızdırmaktan hoşlandığı. Elbette buna cevap vermek için hiçbir neden yok ve makul bir argüman olduğunu düşünen herkes yine de konuşmanın ötesinde.

En nesnel noktası olarak nelerin parlayabileceğine gelince:

  • STL ve Boost tam bir saçmalık <- her neyse. Sen bir salaksın.
  • STL ve Boost sonsuz miktarda ağrıya neden olur - saçma. Açıkçası bilerek aşırı abartıyor ama o zaman burada gerçek ifadesi nedir? Bilmiyorum. Ruh'ta derleyici kusmuğuna neden olduğunuzda sorunların çözülmesi için biraz daha zor olan bazı şeyler vardır, ancak boşlukların * gibi C yapılarının yanlış kullanılmasından kaynaklanan UB'yi ayıklamaktan daha az ya da çok zor değildir.
  • C ++ tarafından teşvik edilen soyut modeller yetersizdir. Ne gibi? Asla genişlemiyor, ne anlama geldiğine dair hiçbir örnek vermiyor, sadece söylüyor. İDT. Neye atıfta bulunduğunu söyleyemediğim için, ifadeyi "çürütmek" için küçük bir nokta var. Bu, C bigots'un ortak bir mantrasıdır, ancak bu onu daha anlaşılabilir veya anlaşılır kılmaz.
  • Doğru C ++ kullanımı, kendinizi C yönüyle sınırladığınız anlamına gelir. Aslına bakarsanız WORSE C ++ kodu bunu yapar, bu yüzden hala konuştuğu WTF'yi bilmiyorum.

Temel olarak, Torvalds kıçından çıkıyor. Hiçbir şey hakkında anlaşılabilir bir tartışma yoktur. Böyle bir saçmalık ciddi bir çürütme beklemek sadece aptalca. Söylediğim yerdeyse, genişletmem beklediğim bir şeyle ilgili olarak "genişletmem" isteniyor. Eğer gerçekten, dürüstçe, Torvalds'ın gerçekte bir şey söylemediğini göreceğini söylediğine bakın.

Sadece Tanrı, bunun bir anlam ifade etmediğini veya bazı rastgele bozoların söylediğinden daha ciddiye alınması gerektiğini söylemediği için. Gerçeği söylemek gerekirse, Tanrı başka bir rastgele bozo.


Asıl soruya cevap verme:

Muhtemelen en kötü ve en yaygın olan kötü C ++ uygulaması, C gibi davranmaktır. Printf, c (ayrıca C de kötü kabul edilir), strtok, vb. Gibi C API fonksiyonlarının sürekli kullanımı, sadece sağlanan gücü kullanamamaktadır. Sıkı tip sistemde, kaçınılmaz olarak "real" C ++ kodu ile etkileşime girmeye çalışırken daha fazla komplikasyona neden olurlar. Yani temelde, Torvalds'ın tavsiyelerinin tam tersini yapın.

Hataların daha fazla derlenmesinde derleme süresi elde etmek ve hayatınızı diğer genel yollarla kolaylaştırmak için STL ve Yükseltme işleminden yararlanmayı öğrenin (örneğin, yükseltme belirteci hem tip güvenlidir hem de daha iyi bir arayüzdür). İlk başta göz korkutucu olan şablon hatalarını okumayı öğrenmek zorunda kalacaksınız, ancak (yine de deneyimime göre), çalışma zamanında tanımlanamayan davranış oluşturan bir hata ayıklamaya çalışmaktan çok daha kolay. yapmak oldukça kolay.

C'nin iyi olmadığını söyleme. Elbette C ++ daha iyi gibi. C programcıları C'yi daha çok severler. Oyunda takaslar ve öznel beğeniler var. Etrafta dolaşan bir sürü yanlış bilgi ve FUD var. C ++ ile ilgili daha fazla FUD ve yanlış bilgi olduğunu söyleyebilirim ama bu konuda önyargılıyım. Örneğin, “şişkinlik” ve “performans” problemleri C ++ 'nın sözde çoğu zaman büyük sorunlar olmadığı ve kesinlikle gerçekliğin oranlarından mahrum bırakıldığı söyleniyor.

Profesörünüzün bahsettiği konulara gelince, bunlar C ++ 'a özgü değil. OOP'de (ve genel programlamada) kalıtım yerine kompozisyonu tercih etmek istersiniz. Kalıtım, tüm OO dillerinde var olan mümkün olan en güçlü eşleşme ilişkisidir. C ++, daha güçlü bir dostluk ekler. Polimorfik kalıtım, soyutlamaları temsil etmek için kullanılmalı ve "bir-" ilişkisini kullanmalı, asla yeniden kullanım için kullanılmamalıdır. Bu, C ++ 'ta yapabileceğiniz en büyük ikinci hatadır ve oldukça büyük, fakat eşsiz olmaktan çok dilden çok uzak. C # veya Java'da da aşırı karmaşık devralma ilişkileri oluşturabilirsiniz ve bunlar da aynı sorunlara sahip olacaklar.


1
Ironic, 2007'den sonra olduğu gibi git, yalnızca Linux'un sürümlerini yayınladı. Peki, bir benzeri olmayan herhangi bir sistem. Sonra yine, git'in yaratılmasına yol açan koşullar göz önüne alındığında, kesinlikle ona karşı tutmuyorum.
Chris K,

9
Linus, onun için çalışmak isteyen iyi bir C ++ programcısı bulmakta zorlanıyor. Neden acaba? Bence bu sadece bir tavuk ve yumurta türü problemi.
Bo Persson

19

Ben her zaman C ++ 'nın tehlikelerinin deneyimsiz, C sınıfları programcıları tarafından abartıldığını düşündüm.

Evet, C ++, Java gibi bir şeyden daha zor, ancak modern teknikleri kullanarak programlıyorsanız, sağlam programlar yazmak oldukça kolaydır. Dürüstçe yok olduğunu ben Java gibi diller olduğundan daha C ++ bir zaman programlama çok daha zor ve sık sık kendimi ben diğer dillerde tasarım şablonları ve de ray gibi bazı C ++ soyutlamalar eksik buluyorum.

Bununla birlikte, C ++ 'da yıllarca programlama yaptıktan sonra bile, her şimdi ve sonra daha yüksek seviyede bir dilde mümkün olmayan aptalca bir hata yapacağım. C ++ 'daki yaygın bir çöküntü, nesne ömrünü görmezden geliyor: Java ve C #' da genellikle nesne ömrü * ile ilgilenmek zorunda değilsiniz çünkü tüm nesneler öbek üzerinde bulunur ve sizin için sihirli bir çöp toplayıcı tarafından yönetilir.

Şimdi, modern C ++ 'da, genellikle nesne yaşamı boyunca da çok fazla ilgilenmenize gerek kalmaz. Sizin için nesnelerin ömrünü yöneten yıkıcı ve akıllı işaretçiler var. Zamanın% 99, bu harika çalışıyor. Ama her şimdi ve sonra, sarkan bir işaretçi (veya referans) ile berbat olacaksınız. Örneğin, yakın zamanda Foobaşka bir nesneye dahili bir referans değişkeni içeren bir nesne (diyelim Bar) diyelim (diyelim ). Bir noktada, aptalca şeyleri daha Barönce kapsam dışına çıkacak şekilde ayarlamıştım Foo, ancak Fooyıkıcısı bir üye işlevini çağırdı Bar. Söylemeye gerek yok, işler iyi gitmedi.

Şimdi, bunun için C ++ 'ı gerçekten suçlayamam. Bu benim kendi kötü tasarımımdı, ama mesele şu ki böyle bir şey üst düzey ve yönetilen bir dilde olmazdı. Akıllı işaretçiler ve benzerleriyle bile, bazen nesne ömrü hakkında bir farkındalığa sahip olmanız gerekir.


* Yönetilen kaynak bellek ise, budur.


8
Java ve C # 'daki nesne kullanım ömrünü hiç dikkate almanıza gerek yok mu? GC'leri hafızayı önemser, ancak bu benim için RAII'nin sadece küçük bir kısmı; Örneğin, bu dillerin sahip olduğu çeşitli "tek kullanımlık" arayüzlere bakın.
Fred Nurk

Nesne ömrü önem zorunda ediyorum I / O kütüphanesinin uygunsuz tasarımı dışında Java nadir.
dan04

Sarkan referans meseleniz, çözmeye çalışmakla ilgilendiğim bir konu. Blogumda çözmeye başladığım yönle ilgili bir tartışma başlattım (işaretçi sözleri). Temel olarak dilin birkaç akıllı işaretçi kullanabileceğini düşünüyorum. İlgileniyorsanız bu tartışmaya katılın. Başka hiç kimse bu kadar neyse olmadı ... ama çözülmüş görmek istersen ... Ben aslında zamanın% 10'undan daha fazlasına rastlarım.
Edward Strange

13

Koddaki fark genellikle programlayıcı ile dilden daha fazla ilgilidir. Özellikle, iyi bir C ++ programcısı ve bir C programcısı da benzer şekilde iyi (farklı olsalar bile) çözümlere gelecektir. Şimdi, C daha basit bir dildir (bir dil olarak) ve bu, kodun gerçekte ne yaptığıyla ilgili daha az soyutlama ve daha fazla görünürlük olduğu anlamına gelir.

Rantının bir kısmı (C ++ 'a karşı öfkesi ile bilinir), daha fazla insanın C ++' ı alacağı ve bazı soyutlamaların neyi gizleyip yanlış varsayımlar yaptığını anlamadan kod yazması gerçeğine dayanmaktadır.


3
std::vector<bool>Değişen her değerin üzerinde yineleme maliyeti nedir ? for ( std::vector<bool>::iterator it = v.begin(), end = v.end(); it != end; ++it ) { *it = !*it; }? İçinde ne soyutlanır *it = !*it;?
David Rodríguez -

2
Her ne kadar geniş çapta yanlışlıklar olarak eleştirilen belirli dil
istismarlarını

2
@Fred Nurk: std::vector<bool>Çok iyi bilinen bir hatadır, ancak tartışılanın gerçekten güzel bir örneğidir: soyutlamalar iyidir, ama ne sakladıklarına dikkat etmelisin. Aynı kullanıcı kodunda da olabilir ve olacaktır. Yeni başlayanlar için, ben akış kontrolü ve kod gerçekleştirmek için istisnalar kullanılarak C ++ ve Java kişilerde hem gördük aslında bir kurtarma istisna başlatıcısı olan bir yuvalama işlev çağrısı gibi görünüyor: void endOperation();olarak uygulanır throw EndOperation;. İyi bir programcı bu şaşırtıcı yapıları önleyecektir , ancak gerçek şu ki, onları bulabilmeniz.
David Rodríguez -

5
Torvalds'ın noktalarından biri şudur: Yeni başlayanları sadece C ++ 'dan C +' yı seçerek (daha fazla C ++ acemi var gibi görünüyor) ve C + 'nın daha karmaşık olması daha dik bir öğrenme eğrisine sahip ve bir köşe olayında daha fazla açma şansı var. .
David Rodríguez -

2
+1, bu tam olarak Linus'un şikayet ettiği şey. C ++ karşıtı olarak çıkıyor, ama o kadar da değil. O sadece anti-C ++ programcısı.
greyfade

13

try/catchBlokların aşırı kullanımı .

File file("some.txt");
try
{
  /**/

  file.close();
}
catch(std::exception const& e)
{
  file.close();
}

Bu genellikle Java gibi dillerden kaynaklanmaktadır ve insanlar C ++ 'ın bir finalizecümlecikten yoksun olduğunu iddia edeceklerdir .

Ancak bu kod iki sorun göstermektedir:

  • Daha fileönce inşa try/catchetmeniz gerekiyor , çünkü aslında içinde olmayan closebir dosyayı yapamazsınız catch. Bu, filekapatıldıktan sonra görünür durumda olan bir "kapsam sızıntısına" yol açar . Bir blok ekleyebilirsiniz ama ...: /
  • Birisi gelir ve kapsamın returnortasına bir tane eklerse try, dosya kapanmaz (bu nedenle insanlar, finalizecümlecik eksikliği konusunda ısırgan olurlar)

Bununla birlikte, C ++ 'da, bu konuyla başa çıkmada çok daha etkili yollarımız var:

  • Java'nın finalize
  • C # 'ın using
  • git adlı defer

Gerçekten ilginç özelliği en iyi SBRM(Scoped Bound Resources Management) olarak özetlenen RAII var .

Sınıfı, yıkıcı, sahip olduğu kaynakları temizleyecek şekilde hazırlayarak, kullanıcısını her birine, kaynağı yönetme sıkıntısı çekmiyoruz!

Bu ben başka bir dilde özledim özellik ve en unutulur muhtemelen.

İşin aslı, nadiren try/catchC ++ 'da bir blok yazmaya bile gerek kalmadan, giriş yapmadan sonlanmamak için en üst seviyededir.


1
Java'nın C kadar etkisi olmadığını sanmıyorum. (Doğrudan fopenve doğrudan kullanabilirsiniz fclose.) RAII burada bir şeyler yapmanın "uygun" yoludur, ancak C ++ 'dan C kütüphanelerini kullanmak isteyenler için uygun değildir. .
dan04, 06.06.2011

Bu tür bir cevap için doğru çözümün bir örneğini sunmak uygun olacaktır.
Claus Jørgensen

@ ClausJørgensen: Maalesef çözüm maalesef "gösterişli" değil çünkü sadece içeriyor File file("some.txt");ve işte bu (hayır open, hayır close, hayır try...)
Matthieu M.

D aynı zamanda
Demi

@Demetri: D'ye fazla aşina değilim, RAII'nin Çöp Toplama ile nasıl etkileşime girdiğini açıklayabilir misiniz? Python'da bir "deinit" yöntemi yazabileceğinizi biliyorum, ancak belgeler referansların döngüsünde bazı nesnelerin deinit yöntemini denenmeyeceklerini belirtir.
Matthieu M.

9

Kriterlerinize uyan yaygın bir hata, sınıfta ayrılan hafıza ile uğraşırken kopya kurucularının nasıl çalıştığını anlamak değildir. Bir 'noob' nesnelerini bir haritaya veya vektöre koyduğundan ve kopya yapıcılarını ve yıkıcılarını düzgün yazmadıklarından dolayı, çökmeleri veya bellek sızıntılarını onarmak için harcadığım zamanın sayısını kaybettim.

Ne yazık ki C ++ 'gizli' gotchas ile doludur. Ama bundan şikayet etmek, Fransa'ya gittiğin ve insanların ne dediğini anlayamadığın gibi. Oraya gidecekseniz, dili öğrenin.


1
Bence C ++ ile ilgili sorun, ayağından vurmak için çok kolay. Elbette, iyi C ++ programcıları var, C ++ ile yazılmış çok iyi yazılımlar var. Ama iyi bir C ++ geliştiricisi olmak çok zor. Scott Meyers 'Efficient C ++' serisi, dilin kaç tane inceliklerini olduğunu gösteriyor.
Marco Mustapic

Katılıyorum. Sorunun bir kısmı, C ++ programcılarının çoğunun (çoğunluğunun) açıkça yapmadıklarında ne yaptıklarını bildiklerini sandıkları yönünde. "Etkili C ++" mu demek istediniz?
Henry,

En azından bu, C ++ 0x ürününde kopya oluşturma / taşıma işlemlerinin örtük olarak üretilmesi konusundaki kısıtlayıcı yeni kurallarla daha iyi bir hale geliyor. Üç kural ihlali vakasının çoğunda, dolaylı kopya oluşturma işlemlerinin kullanımdan kaldırılması ve bir uyarı vermesi gerekir.
sellibitze

6

C ++ , çok çeşitli özelliklere ve programlama stillerine izin verir , ancak bu, bunların C ++ için iyi bir yöntem olduğu anlamına gelmez. Ve aslında, C ++ 'ı yanlış kullanmak inanılmaz derecede kolaydır.

Düzgün bir şekilde öğrenilmesi ve anlaşılması gerekir , sadece yaparak (veya başka bir dili kullanacak gibi kullanarak) öğrenmek, verimsiz ve hataya açık kodlara yol açacaktır.


4

Eh ... Yeni başlayanlar için C ++ SSS Lite'yi okuyabilirsiniz

Daha sonra, birkaç kişi kariyerini C ++ 'nın incelikleri hakkında kitaplar yazdı:

Herb Sutter ve Scott Meyers yani.

Torvalds'ın rant eksikliği olan maddeye gelince ... insanlara ciddiyim, ciddiyim: Dışarıda başka hiçbir dil, dilin nüanslarıyla başa çıkacak kadar fazla mürekkep dökülmedi. Python, Ruby ve Java kitaplarınızın tümü uygulama yazmaya odaklanır ... C ++ kitaplarınız aptal dil özellikleri / ipuçları / tuzaklar üzerine odaklanır.


1
Hmm ... javapuzzlers.com , jimbrooks.org/web/python/#Pitfalls . Ben derim ++ C Hızlandırılmış (bir örneğin) çok odaklar daha bunlardan daha yazma koduna ... nasıl performans gösterdiğine
Jerry Coffin

1
Kendi dillerinde son durumları gösteren birkaç örnek kaynak ortaya koydunuz; garip görünen şeyler ve nasıl çalıştıklarından tam olarak emin değilsin (python listesi yakın olsa da) ... C ++, beklenmedik şekilde davranan mükemmel şekilde geçerli görünen şeyleri gösteren bir endüstriye sahip .
Kızıl-Kir

3

Çok ağır şablonlama ilk başta hatalara yol açmayabilir. Zaman geçtikçe, insanların bu kodu değiştirmesi gerekecek ve devasa bir şablonu anlamakta zorlanacaklar. Bu, böceklerin girdiği zaman - yanlış anlama, genellikle neredeyse ama tamamen doğru olmayan bir kodla sonuçlanan “derler ve çalışır” yorumlarına neden olur.

Genelde kendimi üç seviyeli bir genel jenerik şablon yaparken görürsem durur ve nasıl bire indirgenebileceğini düşünürüm. Çoğu zaman sorun, işlevler veya sınıflar çıkarılarak çözülür.


8
Değişen gereksinimler karşısında karmaşık kodların sürdürülmesi, her zaman çok fazla çaba harcamadan, özellikle de şablonlar için özel bir şey olmadan hatalara neden olur.
Fred Nurk

2

Uyarı: Bu, neredeyse "kullanıcının bilmediği" ifadesinin cevabına bağlı olduğu konuşmanın eleştirisi kadar bir cevap değildir.

İlk ana noktası (sözde) “sürekli değişen standart” tır. Gerçekte, verdiği tüm örnekler bir standart olmadan önce C ++ 'daki değişikliklerle ilgilidir . 1998'den beri (ilk C ++ standardı tamamlandıktan sonra) dilin değişmesi oldukça azdı - aslında, çoğu gerçek sorunun daha fazla değişiklik yapılması gerektiğini savunuyordu . Orijinal C ++ standardına uygun tüm kodların hala geçerli standartlara uyduğundan oldukça eminim. Biraz daha az kesin olsa da , hızlı bir şekilde (ve beklenmedik şekilde) bir şey değişmediği sürece, aynı şey yaklaşmakta olan C ++ standardı için de doğru olacaktır (teorik olarak kullanılan tüm kodlarexportkırılacak, fakat neredeyse hiç yok; pratik açıdan bakıldığında bu bir sorun değil). Bu tür bir iddiada bulunabilecek başka dilleri, işletim sistemlerini (veya bilgisayarla ilgili başka herhangi bir şeyi) düşünebilirim.

Daha sonra "sürekli değişen stillere" gider. Yine, puanlarının çoğu saçmalıklara oldukça yakın. O karakterize etmeye çalışır for (int i=0; i<n;i++)"eski ve kırık" ve for (int i(0); i!=n;++i)"yeni hotness". Gerçek şu ki, bu tür değişikliklerin anlamlı olacağı türler intolsa da, fark yaratmaz - ve bir şey kazanabilseniz bile, iyi veya doğru kod yazmak için nadiren gereklidir. En iyisi bile, köstebek yuvası dışında bir dağ yapıyor.

Bir sonraki iddiası, C ++ 'nın "yanlış yöne doğru optimizasyon yapmak" olduğunu - özellikle, iyi kütüphaneleri kullanmanın kolay olduğunu kabul ederken, C ++' nın iyi kütüphaneleri yazmayı neredeyse imkansız hale getirdiğini iddia ediyor. " Burada, onun en temel hatalarından biri olduğuna inanıyorum. Gerçekte, hemen hemen her dil için iyi kütüphaneler yazmak oldukça zordur. En azından, iyi bir kütüphane yazmak, bir sorunlu alanın anlaşılmasını gerektirir ki kodunuz, söz konusu alandaki (ya da bununla ilişkili) birçok olası uygulama için çalışır. C ++ 'nın gerçekte yaptığı şeylerin çoğu "çıtayı yükseltmek" dir - bir kütüphanenin ne kadar iyi olabileceğini gördükten sonra insanlar nadiren başka türlü sahip olacakları bir yazıyı yazmaya geri dönmeye isteklidirler.gerçekten iyi kodlayıcılar, "geri kalanımız" tarafından (kolayca kabul ettiği gibi) kullanılabilecek birkaç kitaplık yazmaktadır. Bu gerçekten, "bu bir hata değil, bir özellik" olduğu bir durumdur.

Her noktaya (sayfa alacak) sırayla vurmaya çalışmam ama doğrudan kapanış noktasına atlayın. Bjarne'den şunları söylüyor: "kullanılmayan sanal fonksiyon tablolarını ve RTTI verilerini ortadan kaldırmak için tüm program optimizasyonu kullanılabilir. Bu analiz özellikle dinamik bağlantı kullanmayan nispeten küçük programlar için uygundur."

Bunu , durdurulan sorunla karşılaştırarak bile, şu ana kadar "Bu gerçekten zor bir sorun" olduğunu desteklenmeyen bir iddiada bulunarak eleştiriyor . Gerçekte, bu tür bir şey değil - aslında, Zortech C ++ (hemen hemen 1980'lerde MS-DOS için ilk C ++ derleyicisi) içerdiği bağlayıcı . Muhtemelen yabancı verilerin her bir parçasının kaldırıldığından emin olmak zor, ancak oldukça adil bir iş yapmak için hala tamamen makul olduğu doğru.

Bununla birlikte, bunun ne olduğuna bakılmaksızın, en önemli nokta, bunun her durumda çoğu programcı için tamamen ilgisiz olmasıdır. Oldukça fazla kod çözenlerin bildiği gibi, hiç kütüphanesi olmayan bir montaj dili yazmıyorsanız, çalıştırılabilir dosyalarınız neredeyse kesinlikle makul miktarda "malzeme" (hem kod hem de veri) içerir. Muhtemelen hiç bilmiyorum, hiç kullanmadan bahsetmiyorum bile. Çoğu insan için, çoğu zaman, sadece önemli değil - en küçük gömülü sistemler için geliştirmediğiniz sürece, ekstra depolama tüketiminin basit bir önemi yoktur.

Sonunda, bu rantun, Linus'un aptallığından biraz daha fazla maddeye sahip olmadığı doğrudur - ama bu tam olarak hak ettiği hafif bir övgüyle lanet ediyor.


1

Kaçınılmaz şartlar nedeniyle C ++ kodlamak zorunda olan bir C programcısı olarak, benim deneyimim. Kullandığım çok az şey var C ++ ve çoğunlukla C'ye bağlı. Asıl sebep, C ++ 'ı o kadar iyi anlamıyorum. Bana C ++ 'ın inceliklerini ve iyi kod yazmayı gösteren bir danışmanım yoktu. Ve çok çok iyi bir C ++ kodunun yönlendirmesi olmadan, C ++ 'da iyi kod yazmak çok zordur. IMHO bu C ++ 'ın en büyük dezavantajı çünkü yeni başlayanlar elde etmek isteyen iyi C ++ kodlayıcıların gelmesi zor.

Genelde gördüğüm performans isabetlerinin bir kısmı, STL'nin sihirli hafıza tahsisinden kaynaklanmaktadır (evet, tahsisatçıyı değiştirebilirsiniz, ancak bunu C ++ ile başladığında kim yapar?). Genellikle C ++ uzmanları tarafından vektörlerin ve dizilerin benzer performans sunduğunu gösteren argümanları duyarsınız, çünkü vektörler dahili olarak dizileri kullanır ve soyutlama süper verimlidir. Vektör erişimi ve mevcut değerleri değiştirmek için pratikte bunun doğru olduğunu buldum. Fakat yeni bir giriş eklemek, vektörlerin inşası ve imhası için doğru değil. gprof, bir uygulama için kümülatif olarak% 25'inin vektör yapıcılarına, yıkıcılara, hatıralara (yeni eleman eklemek için tüm vektörün yer değiştirmesi için) ve diğer aşırı yüklenmiş vektör operatörlerine (++ gibi) harcandığını gösterdi.

Aynı uygulamada, bir şeyin küçük olanı bir şeyi temsil etmek için kullanılmıştır. Bir şeyde küçük bir şeyin rastgele erişmesine gerek yoktu. Yine de bir liste yerine bir vektör kullanıldı. Vektörün neden kullanıldığını? Çünkü orijinal kodlayıcı, vektörlerin sözdizimi gibi bir diziye aşina idi ve listeler için gereken yinelemelere çok aşina değildi (evet o bir C arka planından geliyor). C ++ 'ya hak kazanabilmek için uzmanlardan birçok rehberliğin gerekli olduğunu kanıtlamaya devam ediyor. C, kesinlikle soyutlama yapmayan çok az temel yapı sunar, C ++ 'dan çok daha kolay elde edebilirsiniz.



0

STL ve boost, kaynak kodu seviyesinde taşınabilir. Sanırım Linus'un bahsettiği konu C ++ 'nın ABI (uygulama ikili arayüzü) içermemesi. Bu nedenle, bağlantı kurduğunuz tüm kütüphaneleri, aynı derleyici sürümüyle ve aynı anahtarlarla derlemeniz ya da kendinizi dll sınırlarında C ABI ile sınırlandırmanız gerekir. Ayrıca bu annyoing buluyorum .. ama 3. parti kütüphaneleri yapmadıkça, inşa ortamınız üzerinde kontrol altına almak gerekir. Kendimi C ABI ile sınırlandırmanın sorun olmaya değmediğini düşünüyorum. Dizeleri, vektörleri ve akıllı işaretçileri bir dll'den diğerine geçirebilme rahatlığı, derleyicileri yükseltirken veya derleyici anahtarlarını değiştirirken tüm kitaplıkları yeniden oluşturma zorunluluğuna değer. İzlediğim altın kurallar:

-Uygulamayı değil arayüzü yeniden kullanmak için miras alın

- Miras üzerinden toplulaştırmayı tercih edin

-Mümkün olan serbest fonksiyonları üye yöntemlere göre seç

-Her zaman kodunuzu kesinlikle istisnai bir şekilde güvenli hale getirmek için RAII deyimini kullanın. Yakalamaya çalışmayın.

-Akıllı işaretçiler kullanın, çıplak (sahipsiz) işaretçilerden kaçının

- Referans anlambilim için değer anlamını tercih etme

- Tekerleği yeniden icat etmeyin, stl kullanın ve artırın

-Pimpl deyimini özel gizlemek ve / veya bir derleyici güvenlik duvarı sağlamak için kullanın


-6

;En azından bazı VC versiyonlarında, bir klan bildiriminin sonunda final vermemek.


4
Bu belki de yeni başlayanlar için çok yaygın bir hatadır (hâlâ temel sözdizimini öğrenen biri için neredeyse her şey olduğu gibi), ancak kendilerini yetkin olarak adlandıran ve hala bu hatayı dikkat çekici bulan birçok kişi var mı?
Fred Nurk

1
Bunu sadece derleyicinin noktalı virgül eksikliği ile ilgisi olmayan bir hata verdiği için yazdım.
Marco Mustapic

2
evet, tam olarak aynı hata bir C derleyicisinden aldığınız şeydir.
Mircea Chirea
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.