Использование C++ const_cast вместо приведений в стиле C

Почему следующее?:

  const int i0 = 5;
//int       i1 = const_cast<int>(i0);       // compilation error
  int       i2 = (int)i0;                   // okay

  int       i3 = 5;
//const int i4 = const_cast<const int>(i3); // compilation error
  const int i5 = (const int)i3;             // okay

person Community    schedule 16.12.2008    source источник
comment
не могли бы вы добавить сообщения об ошибках от компилятора?   -  person Dmitry Khalatov    schedule 16.12.2008
comment
недопустимое использование const_cast с типом int', which is not a pointer, reference, nor a pointer-to-data-member type invalid use of const_cast with type const int', который не является указателем, ссылкой или типом указателя на член данных   -  person    schedule 17.12.2008


Ответы (4)


  const int i0 = 5;
//int       i1 = const_cast<int>(i0);       // compilation error
  int       i2 = (int)i0;                   // okay

  int       i3 = 5;
//const int i4 = const_cast<const int>(i3); // compilation error
  const int i5 = (const int)i3;             // okay

Ошибки компиляции вызваны тем, что вы не отбрасываете const/не добавляете const. Вместо этого вы копируете i0. Для этой операции вообще не требуется приведение:

int i1 = i0;
const int i4 = i3;

Тип, к которому вы приводите, должен быть указателем или ссылкой. В противном случае использование const_cast не имеет смысла, поскольку вы можете напрямую скопировать его. Для указателей, например, вы можете отказаться от const, потому что разыменование указателя даст другой тип для const T* (выдает const T), чем для T* (выдает T). Для ссылок то же самое: T& будет обращаться к объекту, используя другой тип указателя this, чем const T&. Теперь то, что вы действительно хотели заархивировать:

  const int i0 = 5;
//int &     i1 = const_cast<int&>(i0);      // okay (but dangerous)
  int &     i2 = (int&)i0;                  // okay (but dangerous)

  int       i3 = 5;
//const int&i4 = const_cast<const int&>(i3); // ok now and valid!
  const int&i5 = (const int&)i3;             // okay too!

Вышеупомянутое может привести к неопределенному поведению, когда вы пишете в изначально константный объект через ссылку на неконстантный (на самом деле, простое приведение и чтение не является неопределенным поведением само по себе. Но если вы отбрасываете константу, вы можете также напишите в него, что затем приводит к неопределенному поведению)

person Johannes Schaub - litb    schedule 16.12.2008
comment
Действительно ли поведение undefined просто ИМЕЕТ неконстантную ссылку на константный объект? Я думал, что вам действительно нужно было попытаться изменить его. Ваш пример вообще не обращается к i2; это просто определяет его. - person Rob Kennedy; 16.12.2008
comment
Существуют ли какие-либо ситуации, когда приведение типа C из (int) в (const int) или из (const int) в (int) было бы полезно, поскольку const_cast‹int› и const_cast‹const int› не разрешены? - person ; 18.12.2008
comment
Кенни, нет ситуаций нет. нет постоянных значений rvalue встроенного типа. так что они будут либо незаконными, либо такими же, как int (зависит от того, что говорит стандарт, в настоящее время я не искал их в школе) - person Johannes Schaub - litb; 19.12.2008
comment
Ах. Очень поучительно, спасибо. Приведение константы к ссылке на непостоянную просто кажется безумием. - person Dasaru; 25.06.2012

Это ошибка, потому что стандарт говорит, что это не разрешено. Стандарт перечисляет виды преобразований, которые разрешено выполнять const_cast, и запрещает все, чего нет в списке. Это позволяет следующее:

  • указатели
  • использованная литература
  • Указатели-члены

Поскольку ваши типы не являются ни одним из них, они не разрешены.

С другой стороны, примеры, которые вы привели, также не нужны const_cast.

person Rob Kennedy    schedule 16.12.2008

За первую ошибку. const_cast может использоваться только для типов указателей или ссылок. "int" не является ни тем, ни другим. Это может быть или не быть стандартом С++ (не удалось найти хорошую ссылку). Но это касается некоторых реализаций, таких как компилятор MS C++.

По второй ошибке. const_cast можно использовать только для удаления квалификатора const или volatile, но не для его добавления.

Ссылка: http://msdn.microsoft.com/en-us/library/bz6at95h(VS.80).aspx

person JaredPar    schedule 16.12.2008
comment
Оператор const_cast (только C++) Оператор const_cast используется для добавления или удаления модификатора const или volatile к типу или из него. Из: publib.boulder.ibm.com/infocenter/compbgpl/v9v111/ - person ; 17.12.2008

Согласно Справочнику CPP, результатом должен быть указатель или ссылки. При использовании указателя ввод также должен быть указателем. Для ссылок вы можете использовать переменные как входные данные и ссылаться как выходные данные. На странице написано:

lvalue любого типа T может быть преобразовано в ссылку lvalue или rvalue на тот же тип T, более или менее квалифицированный cv. Аналогично, значение prvalue типа class или значение x любого типа может быть преобразовано в более или менее уточненную cv-квалификацию ссылку rvalue.

значение

/* lvalue can be converted to lvalue or rvalue references  */
int& test1 = const_cast<int&>(var);   // lvalue to l-ref; same works for class type
int&& test2 = const_cast<int&&>(var); // lvalue to r-ref; same works for class type
/* prvalues: restriction on built-in types to allow some compiler optimization */
//int&& test5 = const_cast<int&&>(1);            // prvalue of built-in not allowed
A&& test6 = const_cast<A&&>(A());                // prvalue of class type allowed
/* xvalue can be converted to rvalue references */
int&& test8 = const_cast<int&&>(std::move(var)); //xvalue of built-in
A&& test8 = const_cast<A&&>(std::move(A()));     // xvalue of class
person tartaruga_casco_mole    schedule 19.07.2020