Амперсанд в кастинге

Я сталкиваюсь с этим кодом

int n1 = 10;
int n2 = (int &)n1;

Я не понимаю, что значение этого кастинга, n2 не является ссылкой начиная с изменения n1, не отражает n1. Странно этот код бросает ошибку компилятора в gcc где как компиляции, прекрасные в VC ++.

Кто-либо знает значение этого кастинга?

5
задан codaddict 20 October 2010 в 06:58
поделиться

6 ответов

Если предположить, что n2 имеет какой-то встроенный тип, то литой тип int & выполняет переинтерпретацию значения n1 (независимо от того, какой тип он имел) в качестве значения типа int.

В контексте декларации int n2 = (int &) n1, если n1 само по себе является значением типа int, гипс лишний, он абсолютно ничего не меняет. Если n1 является значением типа const int, то бросание просто отбрасывает констелляцию, что также лишнее в приведенном выше контексте. Если n1 является значением какого-то другого типа, то отбрасываемая просто переинтерпретирует память, занятую n1 как объект типа int (это называется типом пробивания int). Если n1 не является значением, то код неправильно сформирован.

Таким образом, в коде типа int n2 = (int&) n1 отбрасывание к int & не является редуцирующим (имеет некоторый фактический эффект), когда оно делает типовую штамповку, т.е. когда n1 является значением какого-то другого типа (не int). Например,

float n1 = 5.0;
int n2 = (int &) n1;

, что было бы эквивалентно

int n2 = *(int *) &n1;

и

int n2 = *reinterpret_cast<int *>(&n1);

Нет необходимости говорить, что это довольно плохая практика программирования.

Это, BTW, один из случаев, когда использование выделенного слепка в стиле Си++ сильно предпочтительнее. Если бы автор кода использовал reinterpret_cast вместо C-style cast, то, наверное, не пришлось бы задавать этот вопрос. Конечно, если n1 сам по себе имеет тип int, то такого рода кастинг не имеет смысла. В таком случае это опять же совершенно лишнее.

P.S. Также существует вероятность, что n2 - это класс с перегруженным оператором преобразования к типу int &, что совсем другое дело.... В любом случае, когда вы задаете подобные вопросы, вы должны сказать, что такое n2.

.
9
ответ дан 18 December 2019 в 06:35
поделиться

Это делает очевидную вещь. Назначьте n1 ссылкой на int, а затем присвойте ее int n2.

И если предположить, что n1 - это int, то он должен скомпилироваться просто отлично.

Он не скомпилируется, если n1 - это значение rvalue. Например:

(int&)foo();
(int&)42;
(int&) (x+y); // assuming x and y are int variables
1
ответ дан 18 December 2019 в 06:35
поделиться

Это совершенно корректный Си++ код, который компилируется с g++ 4.4.1. Он создает временную ссылку на n1, а затем использует значение, на которое ссылается эта ссылка, для инициализации n2.

Это может быть проще увидеть, если expresed как функция:

void f( int & n1 ) {
   int n2 = n1;   // initialise with valuue referred to by n1
}

Обратите внимание, что это недействительный код C, так как C не поддерживает ссылки.

.
11
ответ дан 18 December 2019 в 06:35
поделиться
int main()
{
        int n1 = 10;
        int n2 = (int &)n1;
        cout<<n2<<endl;
}

Печатает 10, как и ожидалось.
С актерским составом проблем нет.
Просто создается временная ссылка, как предполагает следующий вывод:

int main()
{
        int n1 = 10;
        int n2 = (int &)n1;
        n2 = 20;
        cout<<n1<<endl; // print 10 and not 20.
}
2
ответ дан 18 December 2019 в 06:35
поделиться

Я думаю, что это, вероятно, опечатка в оригинальном коде.

GCC обычно более педантичен, чем VC++. Однако этот код кажется неплохим, хотя и делает ненужные вещи. В основном создается временная ссылка для n1, а затем конструктор копирования используется для инстанцирования n2.

.
1
ответ дан 18 December 2019 в 06:35
поделиться

Он тоже компилируется в gcc (я просто пытался быть уверенным). Он просто приводит n1 к ссылке.

0
ответ дан 18 December 2019 в 06:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: