Ваш код на самом деле не 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»).