C ++ benzeri const'u bir dile getirmenin sorunları nelerdir?


17

Ben C ++ fikri ile ilgileniyorum - constbelirli bir yürütme gibi değil (döküm gibi const).

Örneğin C # - C ++ benzeri const yoksun ve bunun nedeni normal - insanlar ve zaman. Burada ek olarak C # ekibi const, CLR'nin C ++ uygulamasına baktı ve bu noktada yeterliydi ( c # ve const parametresinde neden const üye yöntemi olmadığına bakın ; teşekkürler Svick). Bundan daha ileri gidersek , başka bir şey var mı?

Daha derin bir şey var mı? Örneğin çoklu miras alın - genellikle kavraması zor (kullanıcı için) ve bu nedenle dile eklenmez (elmas problemi gibi).

İçinde orada şey mi DOĞA ait constbu dil bunu önlemek için daha iyi bir sorun poz? constDerin mi yoksa sığ mı olacağına karar vermek gibi bir şey ( constkonteynere sahip olmak , yeni eleman ekleyemediğim veya mevcut elemanları değiştiremediğim anlamına gelir; elemanlar referans tipindeyse?)

GÜNCELLEME : C # 'dan bahsederken ve böylece tarihsel bir perspektif constoluştururken, dilin potansiyel sorunlarının doğasıyla ilgileniyorum .

Bu diller için bir meydan okuma değil. Lütfen güncel eğilimler veya popülerlik gibi faktörleri göz ardı edin - Yalnızca teknik sorunlarla ilgileniyorum - teşekkür ederim.


3
bir kenara: çoklu kalıtımın kavranması zor olmayabilir, ancak yöntem çözünürlüğü oldukça çirkinleşebilir. Saf derinlik-ilk çözünürlük hızla sezgisel hale gelir (“ elmas sorunu ”). C3 yöntemi çözünürlük sırası ('96 yayınlanmıştır) bu çözer, ama kesinlikle değil kolay anlaşılması. Bu nedenle, birden fazla mirasın yasaklanması çoğu zaman oldukça mantıklı görünebilir - ancak asıl sorun Java'nın C3 algoritmasından önce gelmesi ve C # 'nin Java'dan sonra yönlendirilmesidir.
amon

3
@amon Pek çok insan aslında çoklu kalıtımın ilk etapta olmasını istediğiniz bir özellik olduğunu düşünmüyor, örneğin D programlama yaratıcıları: Tartışmalı değerin karmaşık bir özelliği. Verimli bir şekilde uygulamak çok zordur ve derleyiciler onu uygulamada birçok hataya eğilimlidir. MI değerinin neredeyse tamamı, arayüzler ve toplama ile birleştirilmiş tek miras ile ele alınabilir. Geriye kalan, MI uygulamasının ağırlığını haklı çıkarmaz. (kaynak)
jcora


2
Hatta olmadan Çoklu Kalıtım yapabilirsiniz zaten böylece NP-tam yapım C # Yöntem Çözünürlük (veya daha doğrusu Aşırı yük Çözünürlük) gibi herhangi bir 3-SAT problemi kodlamak.
Jörg W Mittag

1
@svick, çok teşekkür ederim. Bu soruya cevap bulamadığım için, tarihsel nedenlere değil, sorunun doğasına odaklanmak için çok fazla düzenleme özgürlüğü aldım, çünkü% 99'u "zaman + insanlar + anti C ++ önyargısı + CLR".
greenoldman

Yanıtlar:


10

Bunun sizin için uygun olup olmadığına dikkat edin, ancak Standart ML gibi fonksiyonel dillerde her şey varsayılan olarak değiştirilemez. Mutasyon genel bir reference türü ile desteklenir . Dolayısıyla bir intdeğişken değişmezdir ve bir ref intdeğişken s için değiştirilebilir bir kaptır int. Temel olarak, değişkenler matematiksel anlamda gerçek değişkenlerdir (bilinmeyen ancak sabit bir değer) ve refs, zorunlu programlama anlamında "değişkenler" dir - yazılabilen ve okunabilen bir bellek hücresi. (Onlara atanabilir diyebilirim .

Bence sorun constiki yönlü. İlk olarak, C ++ önemsiz olmayan kalıcı veri yapılarına sahip olmak için gerekli olan çöp toplamadan yoksundur . bir anlam ifade etmek için derin const olmalı , ancak C ++ 'da tamamen değişmez değerlere sahip olmak pratik değildir.

İkincisi, C ++ 'da constbunun dışında kalmayı tercih etmelisiniz . Ancak bir şeyi unuttuğunuzda constve daha sonra düzelttiğinizde, constdeğişikliğin kod boyunca art arda kalacağı @ RobY'nin cevabında belirtilen "const zehirlenmesi" durumu ile sonuçlanacaksınız . Eğer constvarsayılan, sen uygulayarak kendinizi bulmak olmaz constgeriye dönük. Ayrıca, consther yere eklemek zorunda kalmak koda çok fazla gürültü ekler.

İzleyen ana dillerin (örn. Java) C ve C ++ 'ın başarısı ve düşünme tarzı tarafından büyük ölçüde şekillendiğinden şüpheleniyorum. Durumda, çöp toplamada bile çoğu dilin toplama API'ları değiştirilebilir veri yapıları varsayar. Her şeyin değişebilir olması ve değişmezliğin bir köşe vakası olarak görülmesi, popüler dillerin arkasındaki zorunlu zihniyet hakkında çok şey anlatıyor.

EDIT : Greenoldman'ın yorumunu yansıttıktan sonra constbunun doğrudan verilerin değişmezliği ile ilgili olmadığını fark ettim ; constörnek üzerinde yan etkileri olup olmadığı yöntemin türüne kodlar.

Referans olarak şeffaf davranışlar elde etmek için mutasyon kullanmak mümkündür . Diyelim ki art arda çağrıldığında farklı değerler döndüren bir işleve sahipsiniz - örneğin, tek bir karakteri okuyan bir işlev stdin. Referans olarak saydam bir değer akışı üretmek için bu işlevin sonuçlarını önbellek / not kullanarak kullanabiliriz. Akış, değerlerini ilk kez almaya çalıştığınızda düğümleri işlevi çağıracak, ancak sonucu önbelleğe alacak olan bağlantılı bir liste olacaktır. Eğer stdintutarsa Hello, world!, ilk düğümün değerini ilk kez almaya çalıştığınızda, bir tane okuyacak charve geri dönecektir H. Daha sonra H, bir daha okumak için çağrı yapmadan geri dönmeye devam edecektir char. Benzer şekilde, ikinci düğümün bir şeklinde olur chardanstdindeğerini ilk kez almaya çalıştığınızda, bu kez ebu sonuç döndürülür ve önbelleğe alınır.

Buradaki ilginç şey, doğası gereği durum bilgisi olan bir süreci görünüşte vatansız görünen bir nesneye dönüştürmüş olmanızdır. Bununla birlikte, bunu başarmak için nesnenin iç durumunu (sonuçları önbelleğe alarak) değiştirmek gerekiyordu - mutasyon iyi huylu bir etkiydi . Akımın değişmez bir değer gibi davranmasınaCharStream const rağmen, bunu yapmak imkansızdır . Şimdi yöntemlerle bir arayüz olduğunu ve tüm fonksiyonlarınızın beklediğini düşünün . Sizin arabirimini uygulayamaz!Streamconstconst StreamsCharStream

( DÜZENLEME 2: Anlaşılan anahtar denilen bir C ++ var mutableolduğunu bize hile ve yapmak olanağı sağlayacakCharStream const Ancak bu mazgal yok eder. const'Ler garanti - şimdi gerçekten bir şey mutasyon onun aracılığıyla olmayacak emin olamaz constyöntemlerle Ben öyle değil herhalde. Bu açık deliği açıkça istemelisiniz, ancak onur sistemine hala tamamen güveniyorsunuz.)

İkinci olarak, üst düzey işlevlere sahip olduğunuzu varsayalım - yani işlevleri diğer işlevlere bağımsız değişken olarak iletebilirsiniz. constness bir işlevin imzasının bir parçasıdır, bu nedenle constişlev olmayan işlevleri işlev bekleyen constişlevlere argüman olarak iletemezsiniz . constBurada körü körüne uygulamak genellemenin kaybına yol açacaktır.

Son olarak, bir constnesneyi manipüle etmek , onun arkanızdaki bazı harici (statik veya global) durumu mutasyona uğratmadığını garanti etmez, bu nedenle constgarantiler başlangıçta göründükleri kadar güçlü değildir.

Yan etkilerin varlığını veya yokluğunu tip sistemine kodlamanın evrensel olarak iyi bir şey olduğu bana açık değil.


1
+1 teşekkür ederim. Değişmez nesneler C ++ sabitinden başka bir şeydir (daha çok bir görünümdür). Ama diyelim ki, C ++ varsayılan olarak const olurdu ve vartalep üzerine sadece bir sorun bırakacaktı - derinlik?
greenoldman

1
@greenoldman İyi bir nokta. C ++ kullandığımdan beri bir süre geçti, bu yüzden nesne constolmayan bir referansa sahip olabileceğinizi unuttum const. Yine de, sığ olmanın mantıklı olduğuna inanmıyorum const. Bütün mesele, constbu referans aracılığıyla nesneyi değiştiremeyeceğinizin garantisidir. Referans constolmayan bir constreferans oluşturarak atlatmanıza izin verilmiyor , o zaman neden constnesnenin üyelerini değiştirerek atlatmak uygun olur ?
Doval

+1 :-) Güncellemenizde çok ilginç konular (const olmayan lambdaslarla yaşamak ve dış durumla belki de daha zayıf bir problem), daha uzun sindirmek zorundayım. Her neyse, yorumunuza gelince aklımda kötü bir şey yok - tam tersine, kodun netliğini artırmak için özellikler arıyorum (başka bir tane: boş olmayan işaretçiler). Burada aynı kategori (en azından benim amacım) - Ben tanımladım func foo(const String &s)ve bu bir sinyal sdeğişmeyecek foo.
greenoldman

1
@greenoldman Temyiz ve mantığı kesinlikle görebiliyorum. Bununla birlikte, soruna mümkün olduğunca değişebilir durumdan kaçınmaktan başka gerçek bir çözüm olduğunu düşünmüyorum (diğer kötü şeylerle nullve miraslarla birlikte)
Doval

8

Ana sorun, programcıların yeterince kullanmama eğiliminde olmalarıdır, bu nedenle gerekli olan bir yere çarptıklarında veya bir bakımcı daha sonra sabitliği düzeltmek istediğinde, büyük bir dalgalanma etkisi vardır. Yine de mükemmel bir şekilde iyi değiştirilemez kod yazabilirsiniz const, derleyiciniz bunu zorlamayacak ve optimize etmek için daha zor bir zamana sahip olacak. Bazı insanlar derleyicilerini onlara yardım etmemeyi tercih ediyor. Bu insanları anlamıyorum, ama birçoğu var.

İşlevsel dillerde, hemen hemen her şey vardır constve değişebilir olmak, izin verilirse nadir istisnadır. Bunun daha kolay eşzamanlılık ve paylaşılan durum hakkında daha kolay akıl yürütme gibi çeşitli avantajları vardır, ancak değişebilir bir kültüre sahip bir dilden geliyorsanız alışmak biraz zaman alır. Başka bir deyişle, istememek constbir teknik değil, bir insan meselesidir.


+1 teşekkür ederim. Değişmez nesne aradığımdan başka bir şey olsa da (nesneyi C # veya Java'da değişmez hale getirebilirsiniz), değişmez yaklaşımla bile derin veya sığ olup olmadığına karar vermelisiniz, örneğin işaretçiler / referanslar kabını alın ( nokta olan nesnelerin değerini değiştirin ). Bir günden sonra ana sorun, varsayılan olarak ayarlanan şeydir ve yeni dil tasarlanırken kolayca çözülebilir.
greenoldman

1
"Bazı insanlar derleyicilerini onlara yardım etmemeyi tercih ediyor. Bu insanları anlamıyorum, ama birçoğu var."
Thomas Eding

6

Dezavantajları şöyle görüyorum:

  • "const zehirlenmesi", bir const bildirimi önceki veya sonraki bir bildirimi const kullanmaya zorlayabiliyorsa ve bu, önceki bildirimlerin önceki ifadelerinin const, vb. üzerinde kontrol sahibi olmadığınızı, o zaman kötü bir yerde sıkışıp kalabilirsiniz.

  • bu mutlak bir garanti değildir. Genellikle sabitin sadece referansı koruduğu, ancak temelde yatan değerleri bir nedenden ötürü koruyamadığı durumlar vardır. C'de bile, const'ın ulaşamayacağı, const'un verdiği sözü zayıflatan kenar durumlar vardır.

  • genel olarak, endüstrinin duygusu güçlü derleme zamanı garantilerinden uzaklaşıyor gibi görünüyor, ancak size ve ben getirebilirler. Adam 10 mükemmel işlenebilir, iyi tasarlanmış, iyi test edilmiş, tamamen işlevsel Python modülleri vurdu. Ve bunu yaparken bile hacklemiyordu.

Öyleyse belki de soru şu ki, neden bazı uzmanların bile yeni dilinizi benimsemeye çalıştığınız konusunda kararsız olan potansiyel olarak tartışmalı bir özellik öne sürüyoruz?

EDIT: kısa cevap, yeni bir dil benimsenmesi için tırmanmak için dik bir tepe vardır. Tasarımcıların benimsenmesi için hangi özelliklere ihtiyacı olduğunu gerçekten düşünmesi gerekiyor. Örneğin Go'yu ele alalım. Google, Conan-the-Barbarian tarzı tasarım seçimleri yaparak en derin dini savaşların bazılarını acımasızca kesmişti ve aslında dilin gördüklerimden daha iyi olduğunu düşünüyorum.


2
İkinci merminiz doğru değil. C ++ 'da, wrt referans / işaretçi bildirmenin üç / dört yolu vardır. constness: int *değişebilir değere int const *değişebilir işaretçi, sabit değere int * constdeğişebilir işaretçi, değişebilir değere int const * constsabit işaretçi, sabit değere sabit işaretçi.
phresnel

Teşekkür ederim. Ben doğayı sordum, pazarlama ("sanayi uzaklaşıyor" C ++ benzeri bir doğa değil const), bu nedenle bu tür "nedenler" önemsiz (en azından bu soru için) düşünüyorum. Hakkında constzehirlenmesi - Eğer örnek verebilir? Çünkü AFAIK avantajdır, bir şey geçirirsiniz constve kalır const.
greenoldman

1
O değil constsorun ama gerçekten türünü değiştirmek - ne yaparsanız yapın, her zaman bir sorun olacaktır. Geçmeyi düşünün RichStringve sonra daha iyi geçtiğinizi fark edin String.
greenoldman

4
@RobY: İkincisi ve eskisi ile neye / kime hitap ettiğinden emin değilim . Ancak, öğleden sonra kodda yürüdükten sonra, yukarıdan aşağıya değil, aşağı doğru değil, aşağı doğru değil, yani en içteki birimlerden başlayıp yukarı doğru çalışmanız gerektiğini düşünmelisiniz. Belki de üniteleriniz de yeterince izole değil, sıkıca bağlanmıştı ya da iç sistemlerin avına düştünüz.
phresnel

7
"Const zehirlenmesi" gerçekten bir sorun değil - gerçek sorun C ++ varsayılan olmayan const. constOlması gerekmeyen şeyleri yapmak çok kolay constçünkü onun yerine onun yerine katılmanız gerekiyor.
Doval

0

constBir dile ekleme konusunda bazı felsefi problemler vardır . Eğer bildirirseniz constbir sınıfa, anlama geldiğini sınıf değiştiremezsiniz söyledi. Ancak sınıf, yöntemlerle (veya mutasyonlularla) birleştirilmiş değişkenler kümesidir. Bir sınıfın durumunu bir takım yöntemlerin arkasına saklayarak soyutlamaya ulaşırız. Bir sınıf devleti gizlemek için tasarlanmışsa, o durumu dışarıdan değiştirmek için mutasyon yapanlara ihtiyacınız vardır ve constartık değildir . Bu yüzden sadece constdeğişmez sınıflara beyan etmek mümkündür . Bu yüzden constsadece sınıfların (veya beyan etmek istediğiniz türlerin const) önemsiz olduğu senaryolarda mümkün görünüyor ...

constYine de ihtiyacımız var mı? Ben öyle düşünmüyorum. constİyi bir tasarıma sahip olmadan kolayca yapabileceğinizi düşünüyorum . Hangi verilere ihtiyacınız var ve nerede, hangi yöntemler veri-veri yöntemleridir ve G / Ç, ağ, görünüm vb. devlete ihtiyaç duymayan değişmez sınıflar.

Sanırım çoğu problem kendini kurtarabilecek, dönüştürebilecek ve çizebilecek büyük yağ veri nesneleri ile ortaya çıkıyor ve sonra bunu örneğin bir oluşturucuya aktarmak istiyorsunuz. Dolayısıyla, büyük bir veri nesnesi için çok pahalı olduğu için verilerin içeriğini kopyalayamazsınız. Ama siz de değişmesini istemiyorsunuz, bu yüzden düşündüğünüz gibi bir şeye ihtiyacınız var const. Derleyicinin tasarım hatalarınızı bulmasına izin verin. Ancak bu nesneleri yalnızca değiştirilemez bir veri nesnesine böler ve yöntemleri sorumlu modülde uygularsanız, işaretçiyi dolaştırabilir (yalnızca) ve değişmezliği garanti ederken verilerle yapmak istediğiniz şeyleri yapabilirsiniz.

C ++ 'da bazı yöntemler constbildirmenin ve diğer yöntemler üzerinde bildirilmemenin mümkün olduğunu biliyorum , çünkü bunlar mutasyona uğradılar. Ve bir süre sonra bir önbelleğe ihtiyacınız var ve sonra bir alıcı bir nesneyi değiştiriyor (çünkü tembel yükler) ve constartık değil. Ama bu soyutlamanın bütün mesele buydu değil mi? Her çağrıda hangi devletin mutasyona uğradığını bilmiyorsunuz.


1
"Yani const sadece sınıfların (veya const bildirmek istediğiniz türlerin) önemsiz olduğu senaryolarda mümkün görünmektedir ..." Kalıcı veri yapıları değişmez ve önemsizdir. Onları C ++ 'da göremezsiniz çünkü hemen hemen hepsi dahili verilerini birden çok örnek arasında paylaşır ve C ++ bu işi yapmak için çöp toplamadan yoksundur. "Bence iyi bir tasarımınız varsa const olmadan kolayca yapabilirsiniz." Değişmez değerler, kodun akıl yürütmesini çok daha basit hale getirir.
Doval

+1 teşekkür ederim. "Bir sınıfa mutabakat beyan etmek" konusuna açıklık getirebilir misiniz? Sınıfı const olarak ayarlamak mı demek istediniz? Evet, bu konuda sormuyorum - C ++ const bir görünüm gibi çalışır, bir sınıf (veya C ++ 11 değişti bir şey) değil, nesnenin yanında bir const bildirebilirsiniz. Ayrıca bir sonraki paragraf ve "kolayca" sözcüğü ile ilgili bir sorun var - C ++ hakkında iyi bir soru var - C # const ve içerdiği iş miktarı çok önemlidir - koymak istediğiniz her tür için const(C ++ anlamda ) tüm özellikler için de arayüz tanımlamanız gerekir.
greenoldman

1
Bir "sınıftan" bahsederken, aslında "bir sınıf örneği" demek istediniz, değil mi? Bence bu önemli bir ayrım.
svick
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.