Амперсанд внутри литья - PullRequest
5 голосов
/ 23 декабря 2009

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

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

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

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

Ответы [ 6 ]

11 голосов
/ 23 декабря 2009

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

Это может быть легче увидеть, если выражать как функцию:

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

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

9 голосов
/ 23 декабря 2009

Предполагая, что n2 имеет некоторый встроенный тип, приведение к типу int & выполняет реинтерпретацию значения lvalue n1 (независимо от того, какой тип он имел) в качестве значения lvalue типа int ,

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

Таким образом, в коде, подобном int n2 = (int&) n1, приведение к int & не является избыточным (имеет некоторый фактический эффект), когда оно выполняет тип punning, т.е. когда n1 является lvalue некоторого другого типа (не *) 1027 *). Например

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

что будет эквивалентно

int n2 = *(int *) &n1;

и

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

Излишне говорить, что это довольно плохая практика программирования.

Это, кстати, один из случаев, когда использование выделенного C ++-стиля настоятельно рекомендуется. Если бы автор кода использовал reinterpret_cast вместо приведения в стиле C, вам, вероятно, не пришлось бы задавать этот вопрос.

Конечно, если n1 сам по себе имеет тип int, то для этого состава нет значимого объяснения. В этом случае, опять же, совершенно излишним.

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

2 голосов
/ 23 декабря 2009
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.
}
1 голос
/ 23 декабря 2009

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

И, предполагая, что n1 является целым числом, оно должно скомпилироваться просто отлично.

Он не скомпилируется, если n1 является значением. Следующее не скомпилируется, например:

(int&)foo();
(int&)42;
(int&) (x+y); // assuming x and y are int variables
1 голос
/ 23 декабря 2009

Я полагаю, что это, возможно, опечатка в исходном коде.

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

0 голосов
/ 23 декабря 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...