2010-01-05 32 views
13

olarak değiştiriyorum Aşağıdaki gibi int const olarak tanımlanan bir değişkenin değerini değiştirmeye çalışıyorum.const değişkeni değerini C++

const int w = 10; 
int* wp = const_cast <int*> (&w); 
*wp = 20; 

aynı bellek konumuna işaret eden her iki ağırlık wp gibi gösterir se değiştirebilir ve hatta atama sonra 10 idi yoktu ağırlık değeri. Ben w doesn ait

const int i = 10; 

değeri gibi const yapmak i beyanı değiştirirseniz

int i = 10; 
const int w = i; 

ilan ederken aşağıda tanımlanan Ama eğer, değişime ağırlık değeri am güçlü değişme. İlk durumda

, değerini nasıl oluyor w, değişmedi rağmen

Farkı [onların adreslerini yazdırırken alıyorum benim izlenim oldu] aynı bellek konumu w ve wp noktası Derleyiciye her iki durumda da farklı davranıyor mu?

Tanımlanma şekline bakılmaksızın, w'nin sıkışmadığından emin olmanın bir yolu var mı? Bir değişkenin tanımını tanımlandığı gibi almayan "

+11

Bir nesne başlangıçta 'const' olarak oluşturulduysa, const_cast' bunu non-'const' olarak yapılamaz (yapmamalısınız); Bu tanımlanmamış bir davranış. Eğer bir nesne başlangıçta "disketsiz" olarak yaratılmışsa, istediğiniz gibi ileri geri alabilirsiniz. –

+5

Bazı uygulamalarda, 'const 'nesnesine yazma işlemi, nesnenin içeriği salt okunur bir bölümde yer alıyorsa (örneğin,' .data' yerine '.data' yerine,' kavramayan verilerin olmadığı durumlarda) programınızı kilitleyebilir.) oturur. –

+6

Kimse bariz soruyu sormamış görünüyor - eğer değeri değiştirmek istiyorsanız, neden değişkeni “const” olarak işaretliyorsunuz? –

cevap

5

. void foo(const int& x) gibi bir const referansı alarak bir yöntem referans olarak const olmayan bir değişkeni geçirecekseniz,değerini foo içinde değiştirmek için const_cast kullanabilirsiniz, ancak yalnızca gerçekte geçirdiğiniz değişken const olmuyorsa ilk yer.

15

Bu, bir const'ın tanımlanmamış olduğu durumlardan biridir, çünkü kod muhtemelen bir değişken değil ve derlenmiş kodda gerçekten bulunmayan şekilde optimize edilmiştir.

aşağıdaki deneyin:

const volatile int w = 10; 
int &wr = const_cast <int &> (w); 
wr = 20; 
std::cout << w << std::endl; 

neyse, ben böyle const_cast kötüye öneriyoruz olmaz.

+3

Sihirli fark "volatile" anahtar kelimesidir. Bunu çıkar ve w = 10, Narendra'nın orijinal işaretçi tabanlı örneğinde olduğu gibi. –

+1

Doğru, uçucu niteleyicinin derleyiciyi en iyi duruma getirmesini engellemek için kullanılır. – rmn

+0

Üç farklı derleyicide de aynısını denedim [Visual C++ Express Edition, g ++ ve Sun CC derleyici], üç derleyicide de sonuç aynıydı. Tüm derleyicilerle sonuçlarda tutarlılık ve dolayısıyla karışıklık vardı. BTW, uçucu ile denedim ve belirtildiği gibi çalıştı. –

0

Tahminimce, w const bildirimi, derleyicinin w değerini ve yeniden sıralama talimatlarını belirtmek gibi daha agresif optimizasyonlar yapmasına izin verir. W'nin değiştiği veya değişmediği, hangi durumda en iyi duruma getirildiğine bağlıdır ve sizin kontrolünüz altında değildir.

Tamamen const olmak için zorlayamazsınız. Cons_cast, programcıya balık gibi şeyler yapabileceklerine dair bir ipucu olmalıdır.

2

Neden sabitleri yeniden bağlayamıyorsunuz? Bunun yerine

const int w = 10; 
int* wp = const_cast <int*> (&w); 
*wp = 20; 
// some code 

sadece aynı adı

const int w = 10; 
{ 
    const int w = 20; 
    // the same code 
} 

kendi değerine bağlı olmalıdır "yeni" sabit, başka bir sabiti (const int _w = w; const int w = _w * 2;) tanıtmak olursa farklı sabit tanıtmak. Gereksiz ödevler derleyici tarafından optimize edilecek - çünkü bu tür bir optimizasyon yaptığını gördük, çünkü sorunuzu sormanızın nedeni bu.

+0

Yuck. Bu işe yarayabilir, ama çirkin. –

+1

Çirkin sabitler, onlarla çalışmak için doğal bir yol olsa da, const_cast 've derleme kodunuz vardır. –

1

İşte bir tazeleme, bunun C dilinde olduğuna dikkat edilmelidir.Bu, const anahtar sözcüğünü kullanarak bir değişken veya işaretçinin kullanılmasının aldatıcı bir şekilde zor bir dayanak noktasıdır. Bu, işaretçi değişkeni foo arasındaki farkı ve söz konusu anahtar kelimeyi kullanarak anlamının nasıl değişebileceğini vurgular.

 
char const *foo; 

char * const foo; 

const char *foo; 

ilk ve son beyanları, veriler örneğin salt okunur ama, adres ‘foo’ ile gösterilen değiştirebilir ‘foo’ ile gösterilen yapar

 
const *char foo; /* OR char const *foo */ 

char str[] = "Hello"; 

foo = &str[0]; /* OK! */ 

foo[1] = 'h'; /* BZZZZTTT! Compile Fails! */ 

yukarıda orta beyanı, verilerin adres yukarıda 'foo'

 
char * const foo; 

char str[] = "Hello"; 

foo = &str[0]; /* BZZZZTTT! Compile Fails! */ 
+0

'const * char foo;' bir hatadır –

+0

'char * const foo;' C++ 'da bir hata (bu soru C++ olarak etiketlenmiştir) - 'const' değişkenleri bir başlatıcıya sahip olmalıdır –

+0

@MM Wow 6 yıl sonra ... xD – t0mm13b

7

koduna göre işaret değiştiremezsiniz yani işaretçi salt okunur yapar i sabit ilan edildi orijinal int, derleyici th kullanma hakkını saklı tutar Çünkü

movl $10, 28(%esp) //const int i = 10; 
    leal 28(%esp), %eax //int* wp = const_cast <int*>(&i); 
    movl %eax, 24(%esp) //store the pointer on the stack 
    movl 24(%esp), %eax //place the value of wp in eax 
    movl $20, (%eax) //*wp = 20; - so all good until here 
    movl $10, 4(%esp) //place constant value 10 onto the the stack for use in printf 
    movl $.LC0, (%esp) // load string 
    call printf //call printf 

: örnek aşağıdaki assembler çevirir Yığında saklanan değer yerine e basit değer. Bu, değerin değişmediği ve orijinal 10 ile sıkıştığınız anlamına gelir.

Hikâyenin ahlakı derleme zamanı sabitleri sabit kalmalıdır çünkü derleyiciye söylediğiniz şey budur. Hikâyenin ahlakı, bir sabitin değişmesi için kabızlığın dökülmesinin kötü şeylere yol açabileceğidir.

2

Sabit değer değiştirilmemelidir. Yapılandırması ve değiştirmeye çalışmasının bir nedeni var, büyük olasılıkla sadece hatalarla sonuçlanacak. Const salt okunur bir bellek bölümünde depolanırsa, erişim ihlallerini alırsınız.

+1

Yeterince adil ve ilk tepkim de olacaktı. Ama gerçek dünyada, bazen yapmalısın. “Const olmasının bir nedeni var,” diyor, aslına göre, aslen yapısını yapan programcı ne yaptığını biliyordu. –

+0

@John: Gerçek dünyada bile bir const değerini değiştirmek için bir sebep yok. Altta yatan sorunu düzeltin, sonra onunla karıştırın. –

0

İyi soru. Bence karışıklık, C++ bağlamına bağlı olarak iki farklı kavram için 'const' anahtar sözcüğünü kullandığı gerçeğinden kaynaklanıyor. Bu kavramlar sabit ve salt okunur değişkenlerdir.

Derleme sırasında bir "const" değişkeni değeri hesaplanabildiğinde, gerçek bir sabit oluşturur. Bu tür sabitlere yapılan referanslar, kullanıldığı zaman değeri ile değiştirilir. Bu nedenle bellekte, kullanıldığı tüm yerleri etkileyecek şekilde değiştirilebilecek bir yer yoktur. #define kullanmak gibidir.

Bir "const" değişkeni değeri derleme sırasında hesaplanamadığında, salt okunur değişken oluşturur. Bellekte bir değer içeren bir değer vardır ancak derleyici salt okunur bir davranışı zorlar.