reinterpret_cast - странное поведение

Я столкнулся с причудливой ошибкой, связанной с reinterpret_cast. Просто посмотрите на код ниже:

int* var;
reinterpret_cast<void const **>(&var);

ошибка в VSC ++ 2010: ошибка C2440: 'reinterpret_cast': невозможно преобразовать из 'int **' в 'const void **'

ошибка в gcc 4.1.2: reinterpret_cast из типа «int **» в тип «const void **» отбрасывает константу

ошибка в gcc 4.6.2: reinterpret_cast из типа «int **» в тип «const void **» отбрасывает квалификаторы

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

Спасибо за помощь!


person user2032932    schedule 01.02.2013    source источник
comment
Отборочные квалификаторы сбивают с толку. Я думаю, что в лучшем сообщении об ошибке были бы указаны квалификаторы изменений.   -  person Vaughn Cato    schedule 01.02.2013
comment
Запутанное и неприемлемое сообщение об ошибке - это одно, но я понятия не имею, почему компилятор считает, что это неправильно.   -  person user2032932    schedule 01.02.2013
comment
Также см. Ответы на stackoverflow.com/questions/14623266/   -  person PlasmaHH    schedule 01.02.2013
comment
Также см. Ответы на stackoverflow.com / questions / 7016098 /   -  person SCFrench    schedule 01.02.2013


Ответы (2)


В разделе 5.2.10 стандарта C ++ 03 рассказывается о том, что может делать reinterpret_cast. Он явно заявляет: «Оператор reinterpret_cast не должен отбрасывать константу».

Отказ от константности определен в разделе 5.2.11 стандарта C ++ 03. Используемая здесь нотация немного сбивает с толку, но в основном она гласит, что приведение между двумя типами «отбрасывает константность», если для данной квалификации нет неявного преобразования.

В вашем случае вы пытаетесь преобразовать int ** в void const**. Компилятор спрашивает: «Могу ли я неявно преобразовать между T ** и T const**?», И ответ отрицательный, поэтому он говорит, что вы отбрасываете константу.

Логика здесь в том, что reinterpret_cast предназначен для обработки изменяющихся типов, а не изменения квалификаторов (для этого и предназначена const_cast). Поэтому, если вы просите его сделать что-то, для чего вам понадобится const_cast, он откажется.

person Vaughn Cato    schedule 01.02.2013
comment
Отличный ответ! Это все объяснило. Спасибо! - person user2032932; 01.02.2013

Чтобы добавить / удалить const, используйте const_cast.

Чтобы справиться с запутанными ошибками приведения, делайте что-то пошагово:

int* var;
int** v2 = &var;
int const** v3 = const_cast<int const**>(v2);
void const** v4 = reinterpret_cast<void const**>(v3);

Обратите внимание, что int const** и int** - очень разные типы, и преобразование между ними опасно - более опасно, чем void* ‹-> int*.

Предположим, у вас есть int** bob. Затем вы передаете его функции, которая принимает от int const** alice до const_cast.

В этой функции они присваивают *alice указатель на int, хранящийся в постоянной памяти, - совершенно законно.

Вне функции вы проверяете, что bob и *bob действительны, затем присваиваете **bob, и вы просто пытаетесь записать в постоянную память.

person Yakk - Adam Nevraumont    schedule 01.02.2013