Я не могу найти много информации по const_cast
. Единственная информация, которую я смог найти (на Stack Overflow):
const_cast<>()
Используется для добавления / удаления сопзЬ (Ness) (или летучего-ность) переменной.
Это заставляет меня нервничать. Могло ли использование const_cast
вызвать неожиданное поведение? Если так, то?
В качестве альтернативы, когда можно использовать const_cast
?
c++
casting
const-cast
Mag Roader
источник
источник
const
объект с помощью деформированнойconst
ссылки / указателя. Если вместо этого вы просто пытаетесьconst_cast
обойти плохо (или, в моем случае, лениво) специфицированный API, который принимает только не-const
ссылку, но будет использоваться только вconst
методах ... никаких проблем.Ответы:
const_cast
безопасно, только если вы приводите переменную, которая изначально не былаconst
. Например, если у вас есть функция, которая принимает параметр aconst char *
, и вы передаете изменяемыйchar *
, можно безопасноconst_cast
вернуть этот параметр обратно в achar *
и изменить его. Однако, если исходная переменная была на самом деле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
источник
§7.1.5.1/4 says Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior
Любая попытка ! Об исходной переменной нет ни слова.const_cast
удаленияconst
из того, что было заявлено изначальноconst
. Но на самом деле попытка записи в этот объект - это UB. Пока вы просто читаете, все в порядке, и самоconst_cast
по себе не вызывает UB. Это ужасная идея, но это не UB по своей сути.Я могу вспомнить две ситуации, когда 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 'this' внутри метода const и изменять члены вашего класса.
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]; } };
источник
const_cast
может ли оно вызывать неопределенное поведение, а не какие его полезные примененияconst_cast
является правильным ответом. Нет никакихhe
вопросов, поскольку только вопрос является предметом.Мне трудно поверить, что это единственная информация, которую вы могли найти о const_cast. Цитата из второго хита Google :
источник
const_cast
. Или вызовите для него метод const.Что говорит Адам. Другой пример, в котором может быть полезно 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; };
Сначала мы добавляем const к типу, на который
this
указывает, затем мы вызываем константную версиюgetT
, а затем мы удаляем const из возвращаемого типа, который действителен, посколькуt
должен быть неконстантным (в противном случае неконстантная версияgetT
не могла иметь был назван). Это может быть очень полезно, если у вас большое тело функции и вы хотите избежать избыточного кода.источник
const_cast
илиstatic_cast
лучше.const_cast
можете делать только то, что вы хотите: изменять cv-квалификаторы.static_cast
может «незаметно» выполнять другие операции, которые вам не нужны. Однако первое применение совершенно безопасно и,static_cast
как правило, безопаснееconst_cast
. Я думаю, что это ситуация, когдаconst_cast
лучше передает ваши намерения, но лучшеstatic_cast
передает безопасность ваших действий.Короткий ответ - нет, это небезопасно.
Длинный ответ таков: если вы знаете достаточно, чтобы использовать его, это должно быть безопасно.
Когда вы выполняете приведение, вы, по сути, говорите: «Я знаю то, чего не знает компилятор». В случае const_cast вы говорите: «Даже если этот метод принимает неконстантную ссылку или указатель, я знаю, что он не изменит параметр, который я ему передаю».
Так что, если вы действительно знаете, что вы утверждаете, что знаете, используя приведение, то это нормально.
источник
Вы уничтожаете любую возможность обеспечения безопасности потоков, если начинаете изменять вещи, которые компилятор считал константными.
источник
const
.const
это доверие.const_cast