const
не означает «это значение может измениться только при особых обстоятельствах».Скорее, const означает: «Ничто из того, что вам разрешено делать, не приведет к каким-либо изменениям (которые вы могли бы наблюдать)»
Если у вас есть переменная, квалифицированная const, вы не сможете,распоряжение компилятора (и ваш собственный выбор, прежде всего, квалифицировать его как const
), чтобы сделать все, что может привести к его изменению.Вот что делает const
.Он может измениться, несмотря на ваши действия, если это постоянная ссылка на неконстантный объект или по любой другой причине.Если вы как программист знаете , что референт на самом деле не является константой, вы можете отбросить его с помощью const_cast
и изменить его.
Но в вашем случае это постоянная переменная-член, это невозможно.Квалифицированная константная переменная не может быть константной ссылкой на неконстантную, потому что это вообще не ссылка.
Редактировать: для захватывающего примера того, о чем это все и почему вы должны вести себя в отношении правильности, давайте взглянем на то, что на самом деле делает настоящий компилятор.Рассмотрим следующую короткую программу:
int main() {
const int i = 42;
const_cast<int&>(i) = 0;
return i;
}
А вот что излучает LLVM-G ++:
; ModuleID = '/tmp/webcompile/_2418_0.bc'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-linux-gnu"
define i32 @main() nounwind {
entry:
%retval = alloca i32 ; <i32*> [#uses=2]
%0 = alloca i32 ; <i32*> [#uses=2]
%i = alloca i32 ; <i32*> [#uses=2]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store i32 42, i32* %i, align 4
store i32 0, i32* %i, align 4
store i32 42, i32* %0, align 4
%1 = load i32* %0, align 4 ; <i32> [#uses=1]
store i32 %1, i32* %retval, align 4
br label %return
return: ; preds = %entry
%retval2 = load i32* %retval ; <i32> [#uses=1]
ret i32 %retval2
}
Особый интерес представляет строка store i32 0, i32* %i, align 4
.Это означает, что const_cast
был успешным, мы фактически присвоили ноль над значением, к которому я был инициализирован.
Но изменения в константных квалификациях не могут привести к заметным изменениям.Таким образом, GCC создает довольно длинную цепочку, в которой 42 помещается в% 0, затем помещается 42 в% 1, затем снова сохраняется в% retval, а затем загружается в% retval2.Таким образом, G ++ будет иметь этот код, удовлетворяющий обоим требованиям, const был отброшен, но не было видимых изменений в i
, main возвращает 42.
Если вам нужно значение, которое можно изменить,например, в элементах стандартного контейнера вам не нужно const
.
Рассмотрите возможность использования private:
членов с методами открытого и закрытого методов получения.