2015-01-30 2 views
1

Я удалял проект, написанный на C++ через GDB, и обнаружил, что const был модифицирован без предупреждения или ошибки компилятором GNU C++.Почему компилятор GNU C++ позволяет вам изменять константу?

Это не программа, которую я был отладки, но это пример поведения я засвидетельствовал:

#include <iostream> 

int main(int argc, char *argv[]) { 
    const int x = 10; 

    int *px = (int *)&x; 
    ++*px; 

    std::cout << "*px: " << *px << "\n"; 
    std::cout << "x: " << x << "\n"; 

    for (int i = 0; i < x; ++i) 
    std::cout << i+1 << "\n"; 

    return 0; 
} 

Я не могу говорить за других компиляторов, потому что я только проверил это с компилятором GNU C++, версия 4.9.2. Почему это разрешено? Это разрушает всю точку const объектов.

Я скомпилировал код выше с г ++ main.c -Wall -Werror

Выход:

*px: 11 
x: 10 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
+5

[Изменение константы не определено] (http://stackoverflow.com/q/22656734/1708801), поэтому результаты непредсказуемы. Компилятор не должен создавать диагностику для неопределенного поведения ... связанный вопрос, вероятно, является дубликатом –

+4

Вот почему вы почти ** не должны использовать C-стиль в C++. – ereOn

+0

точно. предпочитают 'const_cast': P –

ответ

5

Насколько компилятор обеспокоен, вы не изменяя константу. Вы изменяете то, на что указывает указатель на неконстантный int, потому что это то, что отличает (int *), компилятор считает &x as.

Это так называемое C-style cast является самым мощным приложением, предоставляемым C++. Кастинг обычно должен выполняться только в той степени, в которой это действительно необходимо. Во многих случаях достаточно const_cast, static_cast, или dynamic_cast (есть также довольно мощный reinterpret_cast).

Поведение C-стиля заключается в применении наименее мощного приведения, которое требуется для успешной компиляции.

+0

ОК, я принял это, но похоже, что что-то вроде этого должно хотя бы вызвать предупреждение. Пройти через компилятор бесшумно. – ffhaddad

+0

В основном это наследие C, где такое литье было обычным (на самом деле, изначально это был единственный доступный метод кастинга, и это позволяло почти что угодно). Это и есть причина для введения бросков, упомянутых в моем ответе. Листинг C-стиля все еще существует для обратной совместимости, но использование его не рекомендуется. – Dabbler

+1

@ffhaddad Другая точка зрения: она обычно не проходит через компилятор молча. Обычно вы получаете ошибку: неверное преобразование из 'const int *' в 'int *' ". Приведение говорит компилятору «заткнись, я знаю, что я делаю». – hvd

Смежные вопросы