Привязка значения r к неконстантной ссылке с помощью приведения указателя? - PullRequest
7 голосов
/ 21 февраля 2011

Я не понимаю, как следующий код компилируется / не компилируется:

struct Temp
{
  int i;
};

int main(int argc, char * argv[])
{
   //Temp &ref1 = (Temp){42}; // Error, as expected
   Temp &ref2 = *(Temp*)&(Temp){42}; // A-OK
   std::cerr << ref2.i << std::endl;
   return 0;
}

Я использую g ++ 4.4.4.

Ответы [ 3 ]

2 голосов
/ 21 февраля 2011

Ваш код на самом деле не C ++. Он использует составной литерал, который является функцией C99. В C99 он оценивается как lvalue, и получение адреса литерала там вполне нормально. Интегрируя это расширение в C ++, GCC, похоже, меняет его правило и делает его rvalue, лучше вписывая их классификацию в существующие правила C ++ для обычных приведений, которые также производят rvalue.

GCC не нравится &(Temp){42}, жалуясь, что я беру адрес временный. Это предупреждение о недопустимом коде, который он все еще принимает, но на самом деле не нравится. То же самое предупреждение дается для другого явно неправильного кода, такого как &A(), который является приведением допустимого функционального стиля C ++, который также создает значение r и, следовательно, не может использоваться в качестве операнда оператора address-of.

Интеграция составных литералов в C ++ с помощью GCC также преждевременно разрушает временные данные, как видно из следующего теста

#include <iostream>
struct B {
  ~B() {
    std::cout << "~B" << std::endl;
  }
};
struct A { int i; B b; };

int main() {
  A *a = &(A){0};
  std::cout << "main" << std::endl;
}

В C99 объект, на который ссылается литерал, будет живым для всего блока (у него будет автоматическая продолжительность хранения). В GNU C ++ объект уничтожается уже в конце полного выражения, еще до того, как будет достигнут конец его блока («~ B» печатается перед «main»).

0 голосов
/ 21 февраля 2011

Как сказал templatetypedef, это похоже на ошибку в компиляторе. При компиляции с версией GCC 4.6.0 это дает:

error: taking address of temporary [-fpermissive]

И, конечно, с добавлением -fpermissive он компилируется, но жалуется, но все равно не падает и выдает правильный результат. Я думаю, что GCC немного обманывает в "разрешительных" условиях.

0 голосов
/ 21 февраля 2011

Я могу ошибаться по этому поводу, но это похоже на ошибку в компиляторе.Стандарт ISO C ++, §5.3.1 / 2, рассматривает оператор & как

Результатом унарного оператора & является указатель на его операнд. Операнд должен быть lvalue или квалифицированным идентификатором.

В разделе §5.4 / 1 оператор приведен как

Результатвыражение (T) приведенное выражение имеет тип T.Результатом является lvalue, если T является ссылочным типом, в противном случае результатом является rvalue.

Похоже, что

(Temp){42}

Создаетrvalue, которое вам не должно быть разрешено по закону брать адрес использования &.

Я уже делал ошибки при чтении спецификации раньше, поэтому, если кто-то сможет подтвердить это, это будет здорово.

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