Bazı dil özellikleri, ek olsalar bile, dilin pratikte kullanılması gereken yolu değiştirebilir. Bir örnek olarak, bu durumu göz önünde bulundurun:
lock_mutex(&mutex);
// call some functions
...
unlock_mutex(&mutex);
Yukarıdaki kod C ++ 'da uygulanan arama işlevlerini içeriyorsa, bu işlev çağrılarından herhangi birinin atabileceği ve bu istisnai yollardaki muteksin kilidini asla açamayacağımız için bir sorun dünyasında olabiliriz.
Yıkıcılar, programcıların bu noktada kaynakları serbest bırakmayı / serbest bırakmayı unutmamalarına yardımcı olmak için artık elverişli değildir. RAII pratik bir gereklilik haline gelir, çünkü önemsiz olmayan örneklerde fırlatabilecek her bir kod satırını önceden tahmin etmek insanca mümkün değildir (bu satırların şimdi atmayacağını ancak daha sonra değişikliklere neden olabilir). Başka bir örnek al:
void f(const Foo* f1)
{
Foo f2;
memcpy(&f2, f1, sizeof f2);
...
}
Bu tür kod, genellikle C'de zararsız olsa da, C ++ 'da tahribata yol açan cehennem ateşi gibidir, çünkü memcpy
buldozlar bu nesnelerin bitleri ve baytları üzerinde bulunur ve kopya yapıcılar gibi şeyleri atlar. Böyle fonksiyonlar gibi memset
, realloc
, memcpy
, vb C geliştiriciler arasında günlük araçlar bit oldukça homojen bir şekilde eşyalara bakıp kullanılan ve bellekte bayt iken, C daha karmaşık ve daha zengin tipi sisteminin ++ ile uyumlu değildir. C ++, kullanıcı tanımlı türlerin çok daha soyut bir görünümünü teşvik eder.
Dolayısıyla, bu tür şeyler artık C ++ 'a, onu doğru kullanmak isteyen biri tarafından, C'nin salt bir "süperseti" olarak bakmalarına izin vermez. Bu diller, çok farklı bir zihniyet, disiplin ve en etkili şekilde kullanma şeklini gerektirir. .
C ++ 'ı her yönden dürüst olarak gören kampta değilim ve aslında en sevdiğim üçüncü taraf kütüphanelerim bir sebepten ötürü C kütüphaneleridir. Neden tam olarak bilmiyorum ama C libleri doğada daha minimalist olma eğilimindedir (belki de böyle zengin bir tür sistemin bulunmaması, geliştiricilere bazı büyük ve katmanlı soyutlamalar yapmadan gerekli asgari işlevselliği sağlamaya odaklandığından dolayı), ancak çoğu zaman sadece kullanımlarını kolaylaştırmak ve uyarlamak için etraflarına C ++ sarmalayıcıları koymakla bitirdim, ancak bunu yaparken bile minimalist bir yapı benim için tercih ediliyor. Minimalizmi bu tür nitelikleri aramak için fazladan zaman harcayanlar için bir kütüphanenin çekici bir özelliği olarak seviyorum ve belki de C bunu teşvik etme eğilimindedir.
C ++ 'ı çok daha fazla tercih etmiyorum, ancak C API'lerini genellikle en geniş ikili uyumluluk için (ve FFI'ler için) kullanmam gerekiyor, ancak C ++' ı başlıkları için C kullanmasına rağmen uyguladım. Ancak bazen, bir bellek ayırıcısı veya çok düşük seviyeli bir veri yapısının seviyesine (gerçekten gömülü programlama yapanlar arasında daha fazla örnek olduğundan emin olabilirsiniz) olduğu gibi, gerçekten düşük seviyeli olduğunuzda, bazen yararlı olabilir. Çalıştığınız türlerin ve verilerin, değişkenler, maliyet düşürücüler ve yıkıcılar gibi belirli özelliklerin olmadığını varsayabiliriz; böylece bunları karıştırmak, kopyalamak, serbest bırakmak, yeniden tahsis etmek için bit ve bayt olarak değerlendirebiliriz. Çok düşük seviyeli problemlerde, C'nin sağladığı çok daha basit tip bir sistemle çalışmak bazen yararlı olabilir.
Açıklama
Buradaki ilginç bir yorum, biraz daha derinlemesine cevap vermek istedim (buradaki yorumların karakter sınırlaması konusunda çok katı olduğunu düşünüyorum):
memcpy(&f2, f1, sizeof f2);
Foo'nun sahip olduğu herhangi bir işaretçi varsa ya da daha da kötüsü ise, bununla başa çıkacak araçlara sahip olmadığınızdan C de “cehennem ateşi salgını” olur.
Bu adil bir nokta ama odaklandığım her şey ağırlıklı olarak C ++ 'ın tip sistemine ve ayrıca RAII'ye odaklanarak. X-rayish bayt kopyalama nedenlerinden biri memcpy
veya qsort
fonksiyonların türleri daha az C pratik bir tehlike teşkil imha olmasıdır f1
ve f2
(onlar bile önemsiz olmayan yıkımını gerekiyorsa) yıkıcılar resmin içine taşıdığınızda yukarıda oysa açık olan , örtük ve otomatik hale gelirler (genellikle geliştiricilere büyük değer verir). Bu, vptr'ler gibi gizli durumlardan bile bahsetmiyor. f1
İşaretçiler varsa vef2
sığ, onları geçici bir bağlamda kopyalar, daha sonra ikinci kez işaretçilere sahip olanları açıkça serbest bırakmaya çalışmazsak sorun olmaz. C ++ ile bu derleyici otomatik olarak yapmak isteyeceği bir şeydir.
Ve bu, eğer tipik olarak C’de, eğer Foo in in If in in in If If if if bigger bigger bigger bigger typically typically that typically that that that that that that that that that that that that that that that that that that that that that that that that that that becomes becomes becomes becomes becomes ümk ümişe ve bu , “ Foo'nun imleciye sahip olması durumunda”, çünkü kaynak yönetimi ile istenen açıklık, genellikle, C ++’da, artık önemsizce bir UDT yapamayacağımıza, genellikle gözardı edilmesi zorlaştıracaktır. constructible / yıkılabilir sadece o trivially constructible / tahrip olmayan herhangi üye değişkeni depolamak yapma (yine genellikle çok yararlı olur bir bakıma, ama biz gibi kullanım fonksiyonları için cazip değilse tarafından memcpy
veya realloc
).
Benim asıl amacım, bu açıklığın herhangi bir yararını tartışmaya çalışmak değil (eğer varsa, insan hatalarının artmış olma ihtimalinin dezavantajları ile neredeyse her zaman tartılır) derdim, fonksiyonları gibi memcpy
ve memmove
ve qsort
ve memset
verealloc
ve böylece UDT'lerin C ++ gibi özellikler ve yetenekler bakımından zengin bir dilde yeri yoktur. Ne olursa olsun var olsalar da, C ++ geliştiricilerin büyük çoğunluğunun veba gibi bu tür işlevlerden kaçınmanın akıllıca olacağını söylemeye itiraz edilmeyeceğini düşünüyorum. Tip sisteminin çok daha basit ve belki de “daha açık” olması nedeniyle C’de daha az sorun yaşadıklarını savunuyorlar. X-raying C tipleri ve bunları bit ve bayt olarak ele almak hataya açıktır. Bunu C ++ 'da yapmak kesinlikle açık bir şekilde yanlış çünkü bu tür fonksiyonlar dilin çok temel özelliklerine ve tip sistemini neyin desteklediğine karşı savaşıyor.
Bu aslında C'nin en büyük çekiciliği, ancak, özellikle de dil birlikte çalışabilirliği ile ilgili. C # 'nin FFI gibi bir şeyin C +' nin tam gelişmiş tip sistemini ve dil özelliklerini, inşaatçılar, yıkıcılar, istisnalar, sanal fonksiyonlar, fonksiyon / yöntem aşırı yüklemesi, operatör aşırı yüklemesi, tüm çeşitli tiplerde anlamasını sağlamak çok daha zor olurdu. Kalıtım, vb. C ile, birçok farklı dilin doğrudan FFI'ler üzerinden veya dolaylı olarak bazı C API dışa aktarma işlevleri yoluyla istenen biçimde (örneğin: Java Yerel Arabirimi) içe aktarabileceği şekillerde API'ler kadar standart hale gelen nispeten basit bir dildir. ). Ve C'yi kullanmaktan başka çarem kalmadı, bu dilin birlikte çalışabilirliği bizim durumumuzda pratik bir gereklilik.
Ama biliyorsun, ben pragmatistim (ya da en azından olmaya gayret ediyorum). Eğer C bu kadar fakir ve kederliyse, hataya açık, pis bir dil C ++ meraklısı arkadaşlarımdan bazıları olduğunu iddia etti (ve bir şekilde kendi tarafımdan C nefretine yol açmamış olması dışında kendime bir C ++ meraklısı saydım.) Aksine, her iki dili de kendi açılardan ve farklılıklar konusunda daha iyi takdir etmemi sağlama konusunda tam tersi bir etkiye sahipti), o zaman ben gerçek dünyada en ılımlı ve en sızan bir biçimde ortaya çıkmasını bekliyorum. güvenilmez ürünler ve kütüphaneler C'ye yazılmıştır. Bunu bulamıyorum. Linux'u seviyorum, Apache'yi, Lua'yı, zlib'i, OpenGL'yi bu tür değişen donanım gereksinimlerine, Gimp, libpng, Kahire vb. En azından, dilin pozlarını engelleyen her ne olursa olsun, yetenekli ellere bazı güzel kütüphane ve ürünler yazabildiğim kadar etkileyici görünmüyor ve gerçekten ilgilendiğim tek şey bu. Bu yüzden en tutkulu olanlarla hiç ilgilenmedim. pragmatik bir temyizde bulunmak ve "Hey, orada harika şeyler var! Nasıl yaptıklarını öğrenelim ve belki de dilin deyimsel doğasına özgü olmayan, geri getirebileceğimiz güzel dersler vardır. hangi dilde kullanıyorsak onu kullanalım. " :-D