Нет. Этот вопрос не дубликат
Когда следует использовать 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.
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), массивом-указателем (4.2) и функцией-указателем (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
в конце и только указатель не позволяет вам изменить его значение.
Эта проблема прекрасно описана в этот ответ.