Const_cast безопасно?

Я не могу найти много информации о const_cast. Единственная информация, которую я смог найти (о переполнении стека):

const_cast<>()Используется для добавления / удаления сопзЬ (Ness) (или летучего-ность) переменной.

Это заставляет меня нервничать. Может ли использование const_castпричины неожиданное поведение? Если так, то?

Кроме того, когда это можно использовать const_cast?

10.12.2008 21:01:13
В верхнем ответе пропущено что-то, что может быть ужасно очевидным, но стоит заявить: оно становится небезопасным, только если вы пытаетесь изменить исходный constобъект с помощью определенной constссылки / указателя. Если вместо этого вы просто пытаетесь const_castобойти плохо (или, в моем случае, лениво) специализированный API, который принимает только не- constссылки, но будет использоваться только в constметодах ... никаких проблем вообще.
underscore_d 22.12.2015 01:39:30
@underscore_d: более точная версия вопроса (и ответа), которая охватывает следующее: разрешено ли отбрасывать const на объекте, определенном const, если он фактически не изменен?
Peter Cordes 5.02.2019 03:30:40
7 ОТВЕТОВ
РЕШЕНИЕ

const_castбезопасно, только если вы приводите переменную, которая изначально не была const. Например, если у вас есть функция, которая принимает параметр a 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
88
10.12.2008 21:09:59
Неправда. Стандарт С ++. §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 Любая попытка ! Нет слов об исходной переменной.
Alexey Malistov 8.11.2010 15:12:56
@Alexey: исходная переменная - это то, на что указывают или на которые ссылаются. Вы можете взять константную ссылку на неконстантный объект, и, следовательно, приведение его к доступной для записи ссылке является четко определенным поведением, поскольку ссылочный объект на самом деле не является константным.
Puppy 9.11.2010 16:53:29
@ Алексей Малистов: Нет. «Объект» относится к фактической области памяти, занятой в памяти (§1.7). Получение константной ссылки на неконстантный объект не делает объект константным. Только в случае константного ссылочного параметра ( не параметра константного указателя) компилятору разрешается сделать копию в режиме без вывода сообщений (§5.2.2 / 5); это не тот случай, здесь.
Adam Rosenfield 12.11.2010 16:02:57
«Однако, если исходная переменная была фактически const, то использование const_cast приведет к неопределенному поведению». Это утверждение неверно.
Lightness Races in Orbit 3.02.2019 15:30:30
Это не UB, чтобы использовать const_castдля удаления constиз того, что было первоначально объявлено const. Но это UB на самом деле пытаются писать к этому объекту. Пока вы только читаете, у вас все в порядке и само const_castпо себе не вызывает UB. Это ужасная идея, но это не UB.
Jesper Juhl 3.02.2019 16:13:21

Мне трудно поверить, что это единственная информация, которую вы можете найти о const_cast. Цитата из второго попадания Google :

Если вы отбросите константность объекта, который был явно объявлен как const, и попытаетесь изменить его, результаты будут неопределенными.

Однако, если вы отбрасываете константность объекта, который не был явно объявлен как const, вы можете безопасно изменить его.

24
10.12.2008 21:10:29
Grrrreaat ответ, объедините это с этим ответом, и вы получите полную картину.
bobobobo 4.09.2011 14:36:32
хмм. Что касается второго утверждения в вашем ответе, могу я спросить вас, как существует "константность" для объекта, который не был явно объявлен как констант в первую очередь ?.
hAcKnRoCk 16.04.2012 11:40:12
Есть много способов сделать неконстантный объект постоянным, @Iam. Например, передайте объект как параметр const-reference. Или назначьте его указателю на const. Или используйте const_cast. Или вызовите метод const для этого.
Rob Kennedy 16.04.2012 13:15:45

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

5
10.12.2008 21:16:37
Какая? Если у вас есть неизменные (константные) объекты, вы можете тривиальный разделить их между нитями. В тот момент, когда часть вашего кода отбрасывает постоянство, вы теряете всю безопасность потоков! Почему я за это модею? вздох
Matt Cruikshank 10.12.2008 22:53:46
Const, безусловно, является полезным инструментом для создания поточно-ориентированного кода, но он не дает никаких гарантий (за исключением случая констант времени компиляции). Два примера: const-объект может иметь изменяемые члены, а наличие const-указателя на объект ничего не говорит о том, может ли сам объект изменяться.
James Hopkin 11.12.2008 09:29:44
Я думаю, что это хороший ответ, потому что я не думал о чувствах доверия и безопасности оптимизатора компилятора при использовании вами этого слова const. constэто доверие. const_cast
bobobobo 4.09.2011 14:35:13
Относительно изменчивости и безопасности потоков: channel9.msdn.com/posts/…
MFH 21.01.2013 20:25:58

Что говорит Адам. Еще один пример, где 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 к типу thispoints, затем вызываем const-версию getT, а затем удаляем const из возвращаемого типа, который действителен, поскольку tдолжен быть неконстантным (в противном случае неконстантная версия getTне может иметь был назван). Это может быть очень полезно, если вы получили большое тело функции и хотите избежать избыточного кода.

12
9.01.2009 11:57:34
Я бы предпочел использовать статическое приведение для добавления constness: static_cast <const sample *> (this). Когда я читаю const_cast, это означает, что код делает что-то потенциально опасное, поэтому я стараюсь по возможности избегать его использования.
mfazekas 9.01.2009 07:08:39
верно, первым может быть static_cast или даже implicit_cast (boost). Я исправлю это, используя статическое приведение. спасибо
Johannes Schaub - litb 9.01.2009 11:56:46
Я иду вперед и назад о том, лучше const_castили static_castлучше. const_castможет делать только то, что вы хотите: изменить cv-квалификаторы. static_castможет «тихо» выполнять другие операции, которые вы не собираетесь. Тем не менее, первый актерский состав полностью безопасен и, static_castкак правило, безопаснее, чем const_cast. Я думаю, что это ситуация, в которой const_castваша цель лучше передает ваши намерения, но эта static_castинформация лучше передает безопасность ваших действий.
David Stone 21.02.2013 17:21:53

Я могу вспомнить две ситуации, когда const_cast безопасен и полезен (могут быть и другие допустимые случаи).

Один из них - когда у вас есть экземпляр const, ссылка или указатель, и вы хотите передать указатель или ссылку на API, который не является const-правильным, но вы уверены, что не будете изменять объект. Вы можете 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()));
}

Другой случай, если вы используете более старый компилятор, который не реализует 'mutable', и вы хотите создать класс, который является логически постоянным, но не побитовым const. Вы можете 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];
    }
};
34
26.02.2016 22:31:07
Это ... похоже не отвечает на этот вопрос. Он спросил, const_castможет ли это вызвать неопределенное поведение, а не какие его полезные применения
Michael Mrozek 21.05.2014 15:21:32
Из вопроса: "В качестве альтернативы, когда можно использовать const_cast?"
Fred Larson 21.05.2014 15:32:19
Как в «когда это не неопределенно»; он не ищет примеров, когда это полезно
Michael Mrozek 21.05.2014 15:40:38

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

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

Когда вы читаете, то, по сути, говорите: «Я знаю то, чего не знает компилятор». В случае const_cast вы говорите: «Несмотря на то, что этот метод принимает неконстантную ссылку или указатель, я знаю, что он не изменит параметр, который я передаю».

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

10
10.12.2008 22:39:53
#include <iostream>
using namespace std;

void f(int* p) {
  cout << *p << endl;
}

int main(void) {
  const int a = 10;
  const int* b = &a;

  // Function f() expects int*, not const int*
  //   f(b);
  int* c = const_cast<int*>(b);
  f(c);

  // Lvalue is const
  //  *b = 20;

  // Undefined behavior
  //  *c = 30;

  int a1 = 40;
  const int* b1 = &a1;
  int* c1 = const_cast<int*>(b1);

  // Integer a1, the object referred to by c1, has
  // not been declared const
  *c1 = 50;

  return 0;
}

источник: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fkeyword_const_cast.htm

-2
19.07.2012 13:41:31