2013-10-13 12 views
2

C++Cast или преобразовать указатель (T *) на два-сопзе (T сопзЬ * сопзИте) указатель

Я хочу знать, если указатель, который уже не является двух- const указателя (например, T const * const) могут быть неявно или явно лишены, обработаны через что-либо (например, функция) или иным образом преобразованы, чтобы получить T const * const, без или до использования для инициализации переменной, объявленной как T const * const. Как я могу это сделать?

Я подумал, что если бы я начал с T*, то один const_cast (или два, в случае, если бросок может бросить только в одном const в то время) было бы достаточно, но, видимо, это не так. Многие переменные в коде показывают другую неудачную попытку получения T const * const посредством кастинга или возврата из функции. Каждый кастинг не смог вернуть указатель с завершающим const. (Я имею в виду const слева от * в качестве ведущего const и один справа от * в качестве конечного const.) Из-за неудачных бросков я безуспешно пытался принудительно выполнить const с помощью прямой инициализации. Это было составлено в VC11. g++ on stack-crooked.com дает логически эквивалентный вывод консоли, хотя и с разными именами для typeid(/*...*/).name().

#include <iostream> 
#include <typeinfo> 
using namespace std; 

int const * const foo() 
{ 
    return nullptr; 
} 

int main() 
{ 
    int x = 7; 

    auto a1 = &x; 
    cout << typeid(a1).name() << endl; 

    auto a2 = const_cast<int const *>(&x); 
    cout << typeid(a2).name() << endl; 

    auto a3 = const_cast<int * const>(&x); 
    cout << typeid(a3).name() << endl; 

    auto a4 = const_cast<int const * const>(&x); 
    cout << typeid(a4).name() << endl; 

    auto a5 = const_cast<int const * const>(a4); 
    cout << typeid(a5).name() << endl; 

    auto a6 = (int const * const) &x; 
    cout << typeid(a6).name() << endl; 

    auto a7 = static_cast<int const * const>(a4); 
    cout << typeid(a7).name() << endl; 

    auto a8 = reinterpret_cast<int const * const>(a4); 
    cout << typeid(a8).name() << endl; 

    auto a9 = foo(); 
    cout << typeid(a9).name() << endl; 

    int const * const a10 = &x; 
    cout << typeid(a10).name() << endl; 
    cout << (typeid(a10) == typeid(a4)) << endl; 

    auto a12 = a10; 
    cout << typeid(a12).name() << endl; 
    cout << (typeid(a12) == typeid(a4)) << endl; 
} 

Ожидаемые результаты в сравнении фактических результатов, а также вопросы:

Вопрос номера соответствуют тем же номером a# переменных.

  1. Получили ожидаемый результат int *
  2. Получили ожидаемый результат int const *
  3. Ожидаемое int* const, но получил int*. Неужели const_cast проигнорировал свой аргумент const и почему? Поскольку возврат является той же самой константой и типом, что и аргумент, выполнялся ли какой-либо листинг?
  4. Ожидаемое int const * const, но получено int const*. Неужели const_cast проигнорировал свой аргумент const и почему?
  5. Я хотел посмотреть, будет ли const_cast<int const * const> включать трейлинг-код const в результате, если аргумент a4 уже имеет ведущий const. Ожидается int const * const. Получено int const*. Неужели const_cast проигнорировал свой аргумент const и почему?
  6. Ожидаемое int const * const. Получено int const*. Почему явный листинг все же исключает завершающий const?
  7. Ожидаемое int const * const. Получено int const*. Почему static_cast исключает завершающий const?
  8. Ожидаемое int const * const. Получено int const*. Почему reinterpret_cast исключает завершающий const?
  9. Ожидаемое int const * const. Получено int const*. Почему инициализация возвращаемого значения int const * const по-прежнему исключает завершающий const результат?
  10. Ожидаемое int const * const. Получил int const* с выхода консоли, но не от отладчика. a10 явно объявлен как int const * const, так почему же typeid().name() исключает конечный const? operator== дает 1, так почему же именно typeid() (а не только имя) для a10 эквивалентно a4? Отладчик VC11 перечисляет a10 типа int const * const. Почему он отличается от typeid() и typeid().name()? Какой из них правильный?
  11. имя переменной a11 опущено, поскольку оно выглядит как слово «все».
  12. Я ожидал, что a12 будет int const * const, потому что он инициализирован a10, который был явно объявлен int const * const. operator== дает 1, поэтому typeid() по-прежнему int const*. Получил int const* как с выхода консоли, так и с отладчика. Почему они отличаются от ожидаемого результата?

Все литы, возвращаемые функции и инициализации ограничены только литьем в одном const за раз? Является ли ведущим const единственное, что они могут сделать?

ответ

3

const_cast действительно работает так, как вы думаете. Однако auto не делает то, что, по вашему мнению, делает. auto работает аналогично вычету параметра шаблона функции (фактически, он определяется в терминах последнего). Теперь рассмотрим:

template<typename T> 
void f(T x); 

f(42); 
int const n = 42; 
f(n); 

Оба вызова в f<int>(), не f<const int>(). Модификаторы константы верхнего уровня игнорируются путем вычитания параметра шаблона. По той же причине, в этом примере

auto a = 42; a = 84; 
auto b = n; b = 84; 

переменные a и b имеют тип int, не const int, и могут быть изменены.

+0

Спасибо за ответ; что разъясняет многие проблемы, но есть ли у вас ответ на # 10? Кроме того, вы имеете в виду, что ведущий 'const' не является модификатором' const' верхнего уровня; только конечная 'const'? Поскольку 'auto' игнорирует модификаторы констант верхнего уровня, как я могу наблюдать, желательно сохранить, немедленные результаты каждого приведения до того, как будет потерян модификатор const-уровня? Может 'const_cast (& t_type)' придать 'T *' непосредственно в 'T const * const', или мне нужны два приведения, по одному для каждого' const'? – CodeBricks

+1

** 5.2.8/5 ** Квалификаторы верхнего уровня выражения glvalue или * type-id *, которые являются операндом 'typeid', всегда игнорируются. –

+1

Константа, которая применяется к объявляемой переменной, является модификатором 'const' верхнего уровня, независимо от того, лексически ли она появляется в начале или в конце. В 'const int n = 42' и' int const n = 42', модификаторы 'const' являются верхними уровнями. В 'const int * const! p', 'int const * const! p', 'typedef const int * CP; сопз! CP p', я отмечал квалификаторы верхнего уровня с восклицательным знаком. –

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

  • Нет связанных вопросов^_^