C++ модифицирането на 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 може да премахне постоянството или променливостта от всеки указател или препратка, използвайки получения указател или препратка за запис към обект, който е обявен за const или за достъп до обект, който е обявен за volatile, извиква недефинирано поведение. Те дори продължават да предоставят примери по-долу, вторият, който дадох , заявявайки, че трябва да даде недефинирано поведение.

Въпреки това, при компилиране на кода и стартиране (тук), вторият не дава грешка и отпечатва извън 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
Недефинирано означава, че Стандартът не предоставя никакви насоки относно това какво трябва да прави програмата. Това не означава, че ще можете да наблюдавате нещо странно или да получите съобщение за грешка.   -  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-прехвърлянето на нещо различно от действителен const ptr* вероятно е ужасна идея, дори ако наистина работи през повечето време.

Като се има предвид това, причината, поради която вашият код не се компилира правилно, е доста ясна: премахвате постоянството на обекта X, но не успявате да премахнете постоянството и на члена x, който се опитвате да модифицирате.

Опитайте тази:

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