Değişmez ve const arasındaki fark


28

Terimleri sık sık gördüm immutableve constbirbirlerinin yerine kullandım. Ancak, (küçük) tecrübelerime göre, ikisi kodda yaptıkları 'sözleşmede' çok farklıdır:

Immutable, bu nesnenin hiçbir şekilde değişmeyeceği sözleşmesini yapar (örneğin Python tuples, Java dizeleri).

Const, bu değişkenin kapsamında değiştirilmeyeceğine dair sözleşmeyi yapar (bu süre içinde, örneğin C / C ++ anahtar sözcüğü gibi nesneye diğer konuların ne yapabileceği konusunda herhangi bir söz verilmez).

Açıkçası, dil tek iş parçacıklı (PHP) olmadığı ya da doğrusal ya da tek tip olmayan bir yazma sistemine sahip olmadıkça (Clean, Mercury, ATS) ikisi eşdeğer değildir.

İlk olarak, bu iki kavramı anladığım doğru mu?

İkincisi, eğer bir fark varsa, neden neredeyse tamamen birbirlerinin yerine kullanılırlar?


1
consther dilde mevcut değildir ve değişkenlik ve değişkenlik her dilde mevcut değildir, bu yüzden bu dili agonistik yapmak geçerli değildir. Sadece bu kavramların uygulandığı dile özgüdür .

2
İlgili, tavsiye edilen okuma: İmkansızlığın çeşitleri (birkaç C # örneği, fakat büyük ölçüde dil agnostiği ). Biri Eric Lippert'e madalya verdi.

Yanıtlar:


14

Bu farkın en alakalı olduğu yerde C ++ ile konuşacağım.

Doğru bir şekilde not ettiğiniz gibi değişmez , bir nesnenin yaratıldıktan sonra hiçbir şekilde değişemeyeceği anlamına gelir. Bu oluşturma elbette çalışma zamanında gerçekleşebilir, yani bir constnesnenin mutlaka bir derleme zamanı sabiti olması gerekmez. C ++ 'da, (1) ve (2) veya (3) yerine getirildiğinde bir nesne değiştirilemez:

  1. Üye işlevleri mutabletarafından değiştirildiğini bildiren hiçbir üyesi yokturconst

  2. İlan edildi const

  3. constüye işlevleri, herhangi bir üyeyi mutasyona uğratmak için yeterliliği const_castkaldırmak için kullanmazconst

Bununla birlikte, erişim değiştiricileri de düşünebilirsiniz: eğer bir işlem bir örneği dahili olarak değiştiriyorsa, ancak kamusal arayüzü üzerinden gözlemlenebilir olan örneğin durumunu etkilemiyorsa, nesne “mantıksal olarak değiştirilemez”.

Bu yüzden C ++ değişmez nesneler oluşturmak için gerekli araçları sağlar, ancak C ++ 'daki her şey gibi araçlar da yalnızca minimum düzeyde yeterlidir ve gerçekte kullanmaları için özen gerektirir. Bir örneğin durumu, örnek üye değişkenleriyle sınırlı değildir - C ++ referans saydamlığını zorlamak için bir yol sağlamadığından, genel veya sınıf durumunu da içerebilir.

constayrıca C ++ 'da başka bir işlevi vardır: referansları ve işaretçileri nitelemek için. Bir constreferans olmayan bir constnesneye atıfta bulunabilir . Kullanımı (genellikle gerekli olmasa da ya önerilir) yasal const_castbir içinden bir nesneyi mutasyona constreferans ve ancak eğer bu nesne olmayan bildirildi const:

int        i = 4;         // Non-const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Legal.

Ve elbette bir constnesneyi mutasyona çevirmek tanımsız davranışlardır :

const int  i = 4;         // const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Illegal.

19

"Final" anahtar sözcüğünün "const" ifadesini temsil ettiği Java için konuşun:

final Person someone = new Person();

Bu someone, ASLA başka bir Person nesnesine başvuramaz. Ancak, yine de yönlendirilen kişinin ayrıntılarını değiştirebilirsiniz. Örneğinsomeone.setMonthlySalary(10000);

Ancak, someone"Değiştirilebilir" bir nesne olsaydı, aşağıdakilerden biri doğru olurdu: (a) setMonthlySalary (b) adında bir yönteminiz olmazdı setMonthlySalary çağırmak her zaman gibi bir istisna atardıUnsupportedOperationException


10

Değiştirilemeyen nesneler oluşturulduktan sonra durumu değiştirmeyen nesnelerdir. Örneğin;

string prefix = "Pre";
string postfix = "Post";
string myComplexStr = prefix + postfix;

Bu örnekte, myComplexStr nesnesi değişmez ancak değeri hesaplanmadığından sabit değildir. Değişmez çünkü bir dizedir ve statik uzunluk özelliğine sahiptir ve değişemez.

Const nesneleri genellikle Pi, "USA", "StackOverflow.com", port numaraları vb. Derlenmeden önce değerleri bilinen bazı gerçek sabitleri tanımlamak için kullanılır.

Bu açıdan bakıldığında Const, değişmez nesnelerden farklıdır çünkü değerleri program tarafından hesaplanmamaktadır.

Ancak, C ++ 'da "const" anahtar kelimesinden bahsediyorsanız, "const" nin değiştirilemez nesneler oluşturmak için kullanıldığını söyleyebilirsiniz.


1
C ++ 'daki const değişken nesneler oluşturmaz, sadece bir erişim seviyesidir.
Klaim

"Const double pi = 3.14" in nasıl değişken olmadığını açıklayabilir misiniz?
Mert Akcakaya

Nerede olduğuna bağlı. Diyelim ki: "double * p_pi = const_cast <double *> (& pi); * p_pi = 42;" Örneğin. Sonra eğer pi global boşlukta veya ad alanındaysa, bir segmentasyon hatası alıyorum, ama tanımsız davranış olduğuna inanıyorum, belli bir hata değil. Pi, çalışma zamanında kullanılabilir olan, statik olmayan herhangi bir nesnenin üyesiyse, pi == 42 değerini alırım. Gördüğünüz gibi, C ++ 'daki const, erişim seviyesi, semantik değil veri değişkenliği ile ilgili olduğundan, değişken kullanılabiliyor bile kullanılabilir. C ++ 'ta elde etmek neredeyse imkansız. Sadece "taklit" edebilirsiniz. const değiştirilemez.
Klaim

1
@Klaim constNerede olursa olsun, bir benzeri tanımlanmamış tanımlanmış davranış, IIRC. Ve tanımsız davranış, gerçekleşmesi garanti edilen belirli bir hatadan daha kötü . C ++ 'ı artık kullanmadığınız anlamına gelir - C ++ bir constdeğeri değiştirmek için hiçbir yol sağlamaz mutable(elbette üyeler hariç , ancak bu sizin amacınız değildir), C ++ söz konusu olduğunda bunu yapamazsınız. Özel uygulamaların izin verdiği şey tamamen başka bir meseledir (ve optimizasyonlarla derlerseniz, çektiğiniz dublör daha sonra kullandığınız ifadeleri etkilemeyecektir piçünkü yerine geçtikten sonra) etkilemeyecektir .

"C ++ 'daki const değişken nesneler oluşturmaz" hala yanlıştır çünkü kendi cevabınızda belirttiğiniz gibi hala küresel sabitler oluşturur. Anahtar kelime bazı anlamlarda anlamsaldır, aksi halde tanımsız davranışları bile kullanmak için istekliyseniz, her zaman sadece bir hafıza hücresinin voltajını manuel olarak değiştirebilir ve değişmez bir nesnenin değerini değiştirebilirsiniz.
Mert Akcakaya

8

İlk olarak, bu iki kavramı anladığım doğru mu?

Evet ama ikinci sorunuz bu farklılıkları anlamadığınızı gösteriyor.

İkincisi, eğer bir fark varsa, neden neredeyse tamamen birbirlerinin yerine kullanılırlar?

constC ++ 'da değişmezlik için değil, yalnızca erişim seviyesi için kullanılır ("salt okunur" anlamına gelir) . Bu, erişimin kendisinin verilerden tamamen ayrı olduğu anlamına gelir. Örneğin, bazı verileri manipüle edip const referansı ile açığa çıkarabilirsiniz. Erişim salt okunurdur, ancak verilerin tümü tüm datam değişkendir.

const sadece garantee erişim sınırlamaları ise (örneğin D'de benzeri) değişmezlik gerçekten nesnenin hayatın hangi aşamasında olursa olsun verileri değiştirmek için hiçbir şekilde ima .

Artık, C ++ 'daki değişmezliği, bazı verilere const dışında başka bir şekilde erişilmesinin mümkün olmadığından ve başlatıldığından ve daha sonra dokunulmadığından emin olarak simüle edebilirsiniz. Ancak, verilerinizi değişmez olarak işaretlediğinizde D gibi diller size verdiği için bu güçlü bir garanti değildir. Dil, bu verileri değiştiren herhangi bir işlem yapmanın mümkün olmadığından emin olurken, C ++ 'da gerçekte gerekirse konst dökümü ve değişkenliği ile verileri değiştirmeye devam edebilirsiniz.

Sonunda , hiçbir şekilde aynı garantileri sunmadığı gibi aynı değildir.


3

JavaScript’ten bahsetmek, anahtar kelimeler constveObject.freeze

constciltler içinvariables geçerlidir . Değişmez bir cilt oluşturur, ona yeni bir değer atayamazsınız.

Object.freezenesne değerleri üzerinde çalışır. Bir nesneyi değişmez kılar . Yani, özelliklerini değiştiremezsiniz.


0

C ++ 'da aynılar. Her ne kadar consthafızada bir yeriniz varsa ve o hafızaya yazma konusunda OS izniniz varsa bir nesneyi değiştirebilirsiniz .


1
Aslında bu aynı olmadıklarına karşı bir argüman : C ++ değişmez bir anahtar kelime veya dil desteğine sahip değil. Ayrıca, programcının dili aklı başında bir şekilde kullandığını farz ediyorum: aksi halde const de kesinlikle hiçbir değeri yoktur.
K.Steff

1
@ K.Steff - belki de C ++ 'da const tarafından sağlananlar dışında hiçbir ekstra değişmezlik olmadığını söylemek daha iyidir
Martin Beckett

Kesinlikle kesin :)
K.Steff

C ++ 'da hepsi aynı değildir. const "salt okunur" erişim düzeyidir, bu verilerin değişmez olduğu anlamına gelmez. Çoğu zaman C ++ 'da bypass edebilirsiniz.
Klaim

0

C, C ++ ve ilgili dillerde, const olan bir nesne ile sabit referans olan nesneye referansınız veya işaretçiniz arasında da bir fark vardır.

Sabit bir nesneyi değiştirmeye çalışırsanız tanımsız davranış elde edersiniz. ( Sabit bir nesneyi örneğin adresini alarak, adresi const olmayan bir işaretçiye atıp, ardından nesneyi değiştirmek için bu const olmayan işaretçiyi kullanarak değiştirmeyi deneyebilirsiniz ).

Öte yandan sabit işaretçi veya başvuru derleyiciye, nesneyi değiştirmek için bu işaretçiyi veya başvuruyu kullanamayacağınızı söyler. İşaretçiyi veya referansı seçip nesneyi değiştirmeyi deneyebilirsiniz. Nesnenin kendisi sabit olsaydı, kötü şeyler olacak. Nesne aslında sabit değilse, değişecektir. Bu, elbette kodunuzun kullanıcılarının kafasını karıştırabilir ve muhtemelen hatalara neden olabilir.

C, "Merhaba" gibi bir dize değişmezi kullanırsanız, beş karakter ve sondaki sıfır bayt gerçekten sabittir, ancak const olmayan bir işaretçi alırsınız. Const olmayan işaretçiyi nesneyi değiştirmek için kullanmak çok kötü bir fikir.

C'de "const restrict" işaretçisi olabilir. Bu, işaret edilen nesnenin geçici olarak sabit olduğu anlamına gelir. Nesne, "const restrict" işaretçisi kapsamdayken herhangi bir yöntemle değiştirilirse, tanımsız davranışlar elde edersiniz. Bu sadece bir nesneyi bu işaretçiyle değiştirmenizi önleyen bir const işaretçisinden daha güçlüdür.

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.