Отбрасывание константы с помощью const_cast
Нет. Этот вопрос в НЕ повторяется. Когда следует использовать static_cast, dynamic_cast, const_cast и reinterpret_cast?
Заданный здесь вопрос никак не похож на ссылку, описанную как дубликат.
Первый вопрос: я использую const_cast ниже для двух случаев. один из них работает. другой нет.
1. int * const // Работает.
В этом синтаксисе адрес, на который будет указывать переменная, не может быть изменен. Поэтому я использовал const_cast, как показано ниже, и он работает:
`
int j=3;
int *k=&j;
int *m=&j;
int* const i=k;
const_cast<int*>(i)=m; //OK: since i=m would not work so cast is necessary`
2. const int * // Не работает.
Указанный адрес может быть изменен, однако значение не может быть изменено (хотя его можно изменить, указав переменную на другом адресе). Const_cast, который я использую, похоже, не работает здесь:
`
int j=9;
int *k=&j;
const int* i1=0;
i1=k; //OK
//*i1=10;//ERROR.`
Поэтому я попытался выполнить приведение ниже, используя различные способы, но ничего не работает:
const_cast<int*>(i1)=10;
const_cast<int*>(*i1)=l;
*i1=const_cast<int>(l);
*i1=const_cast<int*>(10);
Второй вопрос: все ли броски доступны только для указателей и ссылок? Разве следующий пример недопустим, если на картинке нет указателя или ссылки?
const int a=9;
int b=4;
const_cast<int>(a)=b; //cannot convert from 'int' to 'int'. why is compiler
//trying to convert from int to int anyways or fails
//when both the types are same.
2 ответа
const_cast
применяется к выражениям, а не к объектам, а также является выражением:
§ 5.2.11 [expr.const.cast] / p1:
Результат выражения
const_cast<T>(v)
имеет типT
, ЕслиT
lvalue ссылка на тип объекта, результат lvalue; еслиT
является rvalue ссылкой на тип объекта, результатом является xvalue; в противном случае результатом является prvalue, и в выражении выполняются стандартные преобразования lvalue-to-rvalue (4.1), array-to-pointer (4.2) и function-to-pointer (4.3)v
const_cast<int*>(i)=m;
Этот вызов недопустим, потому что левая сторона присваивания имеет тип значения prvalue и int*
prvalue не поддерживает назначение. Правильный синтаксис будет const_cast<int*&>(i)=m;
, но с тех пор i
в вашем примере было объявлено const
, это вызвало бы неопределенное поведение †.
const_cast<int*>(*i1)=l;
Разыменование указателя типа int*
создает выражение для значения-категории lvalue, и поскольку выражение приведения находится в левой части присваивания, оно должно быть приведено к ссылочному типу lvalue, а именно const_cast<int&>(*i1)=10;
(при условии, что все i1
указывает на не было объявлено const
).
const_cast<int>(a)=b;
const_cast<int>(a)
сама часть является допустимой, в частности, вы можете применить const_cast к выражению, представляющему объект, который не относится к типу указателя и не является ссылочным типом. Но так как он находится на левой стороне задания, он не скомпилируется. И даже если вы измените его на const_cast<int&>(a)=b;
это вызовет неопределенное поведение, потому что a
объявлен const
†.
† § 7.1.6.1 [dcl.type.cv] / p4:
За исключением того, что любой член класса, объявленный mutable (7.1.1), может быть изменен, любая попытка изменить объект const в течение его времени жизни (3.8) приводит к неопределенному поведению.
Первый ответ: в вашем примере вы пытаетесь заставить компилятор сделать что-то, что можно интерпретировать так
const_cast<int*>(i1)=10; //int* = int: assign address to pointer
const_cast<int*>(*i1)=l; //const_cast<int*>(int): cast the value under pointer to pointer
*i1=const_cast<int>(l); //const_casting from const values is forbidden
*i1=const_cast<int*>(10); //10 is an rvalue
Здесь вы действительно хотите разыменовать указатель, который больше не является константным. Вот почему вам нужно сделать это так:
int j = 9;
int *k = &j;
const int* i1 = 0;
i1 = k;
*(const_cast<int*>(i1)) = 10;
что эквивалентно
int j = 9;
int *k = &j;
const int* i1 = 0;
i1 = k;
int* temp = const_cast<int*>(i1); //you get rid of 'const'...
*temp = 10; //...and now you assign value as you wanted to - this operation became available
Второй ответ: запрещено const_cast
константные значения, поскольку это приводит к неопределенному поведению. Вы можете удалить только константу из указателей или ссылок, которые указывают на то, что на самом деле не const
в конце и только указатель запрещает вам изменять его значение.
Эта проблема прекрасно описана в этом ответе.