Использование const_cast в C++ вместо приведений в стиле 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
3 ответа
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 /add const. Вместо этого вы копируете i0. Для этой операции никакое приведение не требуется вообще:
int i1 = i0;
const int i4 = i3;
Тип, который вы приводите, должен быть указателем или ссылкой. В противном случае использование const_cast не имеет смысла, поскольку вы можете скопировать его прямо. Например, для указателей вы можете отказаться от const, потому что разыменование указателя даст другой тип для const T*
(выходы const T
) чем для T*
(выходы T
). Для ссылок то же самое верно: T&
получит доступ к объекту, используя другой тип указателя, чем при использовании 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!
Вышеприведенное может привести к неопределенному поведению, когда вы пишете в изначально const-объект посредством ссылки на неконстантное (на самом деле простое приведение и чтение его не является неопределенным поведением само по себе. Но если вы отбрасываете const, вы можете также написать в него, что затем приводит к неопределенному поведению)
Это ошибка, потому что стандарт говорит, что это не разрешено. Стандарт перечисляет виды конверсий, которые const_cast
разрешено делать, и это запрещает все, что не в списке. Это позволяет следующее:
- указатели
- Рекомендации
- Члены-указатели
Поскольку ваши типы не являются ни одним из них, они не допускаются.
С другой стороны, приведенные вами примеры не нужны const_cast
, или.
Для первой ошибки. const_cast может использоваться только для указателей или ссылочных типов. "int" не является ни тем, ни другим. Это может быть или не быть стандартом C++ (не удалось найти хорошую ссылку). Но это относится к определенным реализациям, таким как компилятор MS C++.
Для второй ошибки. const_cast может использоваться только для удаления const или volatile-квалификатора, но не для его добавления.
Ссылка: http://msdn.microsoft.com/en-us/library/bz6at95h(VS.80).aspx
Согласно ссылке CPP, результатом должен быть указатель или ссылки. При использовании указателя ввод также должен быть указателем. Для справки вы можете использовать переменные в качестве входных данных и ссылаться на них в качестве выходных данных. На странице написано:
lvalue любого типа T может быть преобразовано в ссылку lvalue или rvalue на тот же тип T, более или менее квалифицированный cv. Точно так же prvalue типа класса или xvalue любого типа могут быть преобразованы в более или менее 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