const_cast
безопасно, только если Вы бросаете переменную, которая была первоначально не - const
. Например, если у Вас есть функция, которая берет параметр const char *
, и Вы передаете в модифицируемом char *
, это безопасно к const_cast
, что параметр назад к char *
и изменяет его. Однако, если исходная переменная была на самом деле const
, то использование const_cast
приведет к неопределенному поведению.
void func(const char *param, size_t sz, bool modify)
{
if(modify)
strncpy(const_cast<char *>(param), sz, "new string");
printf("param: %s\n", param);
}
...
char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true); // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true); // UNDEFINED BEHAVIOR
Я могу думать о двух ситуациях, где const_cast безопасен и полезен (могут быть другие допустимые случаи).
Каждый - когда у Вас есть экземпляр константы, ссылка или указатель, и Вы хотите передать указатель или ссылку на API, который не корректен константой, но что Вы УВЕРЕНЫ, не изменит объект. Вы можете const_cast указатель и передавать его API, полагая, что он ничего действительно не изменит. Например:
void log(char* text); // Won't change text -- just const-incorrect
void my_func(const std::string& message)
{
log(const_cast<char*>(&message.c_str()));
}
другой то, если Вы используете более старый компилятор, который не реализует 'изменяемый', и Вы хотите создать класс, который является логически константой, но не поразрядной константой. Вы можете const_cast 'это' в рамках метода константы и изменять членов Вашего класса.
class MyClass
{
char cached_data[10000]; // should be mutable
bool cache_dirty; // should also be mutable
public:
char getData(int index) const
{
if (cache_dirty)
{
MyClass* thisptr = const_cast<MyClass*>(this);
update_cache(thisptr->cached_data);
}
return cached_data[index];
}
};
Мне трудно полагать, что это [только 112] информация, которую Вы могли найти о const_cast. Заключение в кавычки от 110-секундного Google совершило нападки :
, Если Вы выбрасываете constness объекта, который был явно объявлен как константа и попытка изменить его, результаты не определены.
Однако, если Вы выбрасываете constness объекта, который не был явно объявлен как константа, можно изменить ее безопасно.
Что говорит Adam. Другой пример, где const_cast может быть полезным:
struct sample {
T& getT() {
return const_cast<T&>(static_cast<const sample*>(this)->getT());
}
const T& getT() const {
/* possibly much code here */
return t;
}
T t;
};
Мы сначала добавляем, что константа к типу this
указывает на, тогда мы называем версию константы getT
, и затем мы удаляем константу из типа возврата, который допустим, так как t
должна быть неконстанта (иначе, версию неконстанты getT
, возможно, не назвали). Это может быть очень полезно, если Вы получили большое тело функции, и Вы хотите избежать избыточного кода.
Короткий ответ не, это не безопасно.
длинный ответ - то, что, если Вы знаете достаточно для использования его, затем это должно быть безопасно.
то, Когда Вы бросаете, что Вы по существу говорите, "Я знаю что-то, что компилятор не знает". В случае const_cast, что Вы говорите, "Даже при том, что этот метод берет в ссылке неконстанты или указателе, я знаю, что это не изменит параметр, я передаю его".
Поэтому, если Вы действительно на самом деле знаете то, что Вы утверждаете, что знали в использовании броска, затем хорошо использовать его.
Вы уничтожаете любой шанс в потокобезопасности, если Вы начинаете изменять вещи, что компилятор думал, была константа