2011-12-29 7 views
2
int main() 
{ 
    const int maxint=100;//The program will crash if this line is put outside the main 
    int &msg=const_cast<int&>(maxint); 
    msg=200; 
    cout<<"max:"<<msg<<endl; 
    return 0; 
} 

Функция будет работать нормально, если «const int maxint = 100;» определение помещается внутри основной функции, но в случае сбоя и всплытия появляется сообщение об ошибке «Нарушение доступа», если оно установлено снаружи.const cast to global var and program crashed (C++)

Кто-то говорит, что это какое-то «неопределенное поведение», и я хочу знать точный ответ и как я могу безопасно использовать гипс const?

+1

Ваши пугающие цитаты вокруг «неопределенного поведения» подразумевают, что вы не знаете, что это значит - [время для чтения] (http://en.wikipedia.org/wiki/Undefined_behavior). – ildjarn

ответ

9

Они правильные, это неопределенное поведение. Вам не разрешено изменять значение переменной const, что является опасностью отбрасывания const: что-то не так: вам лучше знаю это не действительно const.

Компилятор, видя, что maxint является const и должны никогда быть изменен, даже не дать ему адрес. Он может просто заменить все виды использования maxint со 100, если он сочтет нужным. Кроме того, он может просто поместить константу в часть памяти, которая доступна только для чтения, как указывает Matteo Italia, что, вероятно, является тем, что происходит для вас. Вот почему его изменение приводит к неопределенному поведению.

Единственный путь вы можете смело отбрасывали const ственности переменного, если переменный не является на самом деле const, но const Классификатора был добавлен к не- const переменных, например:

int f(const int& x) { 
    int& nonconst = const_cast<int&>(x); 

    ++nonconst; 
} 

int blah = 523; 

f(blah); // this is safe 

const int constblah = 123; 

f(constblah); // this is undefined behaviour 

Подумайте об этом примере, который компилируется отлично:

int f(const int& x) { 
    int& nonconst = const_cast<int&>(x); 

    ++nonconst; 
} 

int main() { 
    f(4); // incrementing a number literal??? 
} 

Вы можете увидеть, как с помощью const_cast довольно опасно, потому что нет никакого способа, чтобы действительно сказать, является ли в variab le изначально const или нет. Вам следует избегать использования const_cast, когда это возможно (с функциями, просто не принимая параметры const).

+3

Я бы сказал, что здесь компилятор дал адрес константе, но поместил ее в сегмент только для чтения. –

+0

Спасибо! Но у меня все еще возникает вопрос: почему локальная переменная const после const_cast не приведет к сбою программы? – OriginalWood

+2

@OriginalWood undefined поведение - это просто - неопределенное. Он не определен для сбоя. Он может делать что угодно: от работы, до грохота, до поджигания атмосферы. В этом случае это просто сработало. –

0

Вам разрешается отбрасывать постоянную цель объекта, который известен не, являющийся const. Например, интерфейс может передавать объекты с помощью указателя const или ссылки const, но вы передали объект, который не является const, и хотите/должны его изменить. В этом случае может быть правильным отбросить созвездие.

С другой стороны, отбрасывая постоянство объекта, который был const, вы можете столкнуться с серьезными проблемами: при доступе к этому объекту, в частности при записи на него, система может вызывать всевозможные странные вещи: поведение не определено (по стандарту C++) и на конкретной системе, это может вызвать, например, нарушение доступа (поскольку адрес объекта устроен так, чтобы он находился в области только для чтения).

Обратите внимание, что, несмотря на другой ответ, я увидел const объекты должны получить адрес, назначенный, если адрес когда-либо был использован и каким-то образом использован. В вашем коде выражение const_cast<int&>(maxint) по существу получает адрес вашей константы int, который, по-видимому, хранится в области памяти, которая помечена как доступная только для чтения. Интересным аспектом вашего фрагмента кода является то, что он похож на , видимо, работает, особенно при включении оптимизации: код достаточно прост, что компилятор может сказать, что измененное местоположение на самом деле не используется и на самом деле не пытается измените местоположение памяти! В этом случае не сообщается о нарушении доступа.Это то, что, по-видимому, имеет место, когда константа объявляется внутри функции (хотя константа также может быть помещена в стек, который обычно не может быть помечен как только для чтения). Другим потенциальным результатом вашего кода является (независимо от того, объявлена ​​ли константа внутри функции или нет), которая фактически изменяется и иногда считывается как 100 и в других контекстах (которые так или иначе связаны с адресом) как 200.

+1

Незначительный нит: вам разрешено отбрасывать константу объекта const, но вам не разрешается фактически писать на него. –

5

Изменение объекта, которое const (за исключением изменяемых элементов) приводит к неопределенному поведению (от стандарта C++ 03):

7.1.5.1/4 "The CV-Отборочные"

За исключением того, что любой член класса, объявленный измененным (7.1.1), может быть изменен, любая попытка изменить объект const во время i ts lifetime (3.8) в неопределенном поведении.

выше неопределенное поведение специально называется в разделе стандарта на const_cast:

5.2.11/7 «Уст слепок»

[Примечание: В зависимости от типа объекта , операция записи через указатель, lvalue или указатель на элемент данных, полученный из const_cast , который отбрасывает const-qualifier68), может приводить к неопределенному поведению (7.1.5.1). ]

Так что, если у вас есть const указатель или ссылку на объект, который на самом деле не const, вы позволили написать к этому объекту (по отбрасывая константность), но если объект действительно есть const.

Компилятор разрешает размещать const объекты в хранилище только для чтения. Это не обязательно, но, по-видимому, не для вашего тестового кода, который не сбой.

+1

+1 для правильной стандартной цитаты. – ildjarn