С++, изменяющий объект const с помощью указателя const_cast, работает

У меня есть этот фрагмент кода:

#include <iostream>    
using namespace std;

class X {

    public:
        const int x;
        X(int i) : x(i) {  }            
        int getX() const { return x; }           
};

int main()
{
      const X d(45);

      const_cast<X *>(&d)->x = 47;
      cout << d.getX() << endl;

      const int j = 3; // j is declared const
      int* pj = const_cast<int*>(&j);
      *pj = 4; 
      cout << *pj << endl; //should not work, like above

      return 0;
}

Как я нашел здесь, несмотря на то, что const_cast может удалить константность или изменчивость из любой указатель или ссылка, использование результирующего указателя или ссылки для записи в объект, который был объявлен константным, или для доступа к объекту, который был объявлен изменчивым, вызывает неопределенное поведение. Они даже продолжают приводить примеры ниже, второй я дал , заявив, что это должно давать неопределенное поведение.

Однако при компиляции кода и запуске (здесь) второй не выдает ошибок и печатает выходит 4 постоянно. В то время как первый выдает ошибку:

assignment of read-only member 'X::x'                            
       const_cast<X *>(&d)->x = 47;

Конечно, удаление const из объявления x в X заставляет его работать нормально. Тем не менее, это также тот же тип вреда, что и первый, изменение const вещи через указатель после приведения ее const_ptr<>. Но первый работает, а второй нет. Почему так?


person SexyBeast    schedule 11.01.2015    source источник
comment
Неопределенное поведение != Должен сбой. Более того, очень часто это означает, что он работает без видимых признаков неисправности.   -  person Sergey Kalinichenko    schedule 11.01.2015
comment
Итак, 4 я получаю неопределенное поведение? Я не должен получить его?   -  person SexyBeast    schedule 11.01.2015
comment
Undefined означает, что Стандарт не дает никаких указаний относительно того, что должна делать программа. Это не означает, что вы сможете увидеть что-то странное или получить сообщение об ошибке.   -  person molbdnilo    schedule 11.01.2015
comment
@Cupidvogel: Да, получение 4 — это один из возможных случаев неопределенного поведения. Спрашивать, что должно делать неопределенное поведение, бессмысленно.   -  person Mike Seymour    schedule 11.01.2015
comment
Да, да, это то, о чем я говорил, поэтому 4, последовательно приходящие в качестве ответа, являются частью неопределенности и не гарантируются, верно?   -  person SexyBeast    schedule 11.01.2015
comment
Как объяснить неопределенное поведение всезнающим новичкам ? ‹-- Я удивлен, что этот вопрос существует.   -  person    schedule 11.01.2015
comment
Мой вопрос: если оба являются неопределенным поведением, то почему компилятор выдает ошибку в одном случае, а не в другом?   -  person SexyBeast    schedule 11.01.2015


Ответы (2)


Оба требуют неопределенного поведения, что, к сожалению, иногда может означать работу.

   int* pj = const_cast<int*>(&j);
   *pj = 4; 

Кроме того, не все компиляторы достаточно умны, чтобы разобраться в такого рода косвенных манипуляциях.

person ravi    schedule 11.01.2015

Константное приведение к чему-либо, кроме фактического const ptr*, вероятно, ужасная идея, даже если в большинстве случаев это действительно работает.

При этом причина, по которой ваш код не компилируется должным образом, довольно проста: вы удаляете константность объекта X, но вы также не можете удалить константность члена x, который вы пытаетесь изменить.

Попробуй это:

*const_cast<int*>(&(const_cast<X*>(&d)->x)) = 47;
person chili    schedule 02.06.2015