Действительно ли const_cast безопасен?

88
задан msc 28 August 2017 в 11:57
поделиться

6 ответов

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
86
ответ дан Adam Rosenfield 24 November 2019 в 07:32
поделиться

Я могу думать о двух ситуациях, где 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];
    }
};
34
ответ дан Fred Larson 24 November 2019 в 07:32
поделиться

Что говорит 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, возможно, не назвали). Это может быть очень полезно, если Вы получили большое тело функции, и Вы хотите избежать избыточного кода.

11
ответ дан Johannes Schaub - litb 24 November 2019 в 07:32
поделиться

Короткий ответ не, это не безопасно.

длинный ответ - то, что, если Вы знаете достаточно для использования его, затем это должно быть безопасно.

то, Когда Вы бросаете, что Вы по существу говорите, "Я знаю что-то, что компилятор не знает". В случае const_cast, что Вы говорите, "Даже при том, что этот метод берет в ссылке неконстанты или указателе, я знаю, что это не изменит параметр, я передаю его".

Поэтому, если Вы действительно на самом деле знаете то, что Вы утверждаете, что знали в использовании броска, затем хорошо использовать его.

9
ответ дан JohnMcG 24 November 2019 в 07:32
поделиться

Вы уничтожаете любой шанс в потокобезопасности, если Вы начинаете изменять вещи, что компилятор думал, была константа

5
ответ дан Matt Cruikshank 24 November 2019 в 07:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: