Pytanie Jak utworzyć tymczasowy obiekt w C ++


Mam następujący fragment kodu.

class A {
 public:
  A(int) {
  }
};

int a;
int main() {
  A(a);  // Line 'a
  return 0;
}

To, co chcę zrobić na linii "a, to stworzyć tymczasowy A z konstruktorem A::A(int). Wiem, że natychmiast to zniszczy. To jest to czego chce. Ale wygląda na to, że kompilator robi coś podobnego A a, definiowanie zmiennej a od klasy A i zainicjuj go za pomocą konstruktora A::A(). Oczywiście nie istnieje, stąd błąd kompilatora.

Jeśli jednak zmienię mój kod na następujący.

class A {
 public:
  A(int) {
  }
};

void f(A) {
}

int a;
int main() {
  f(A(a));
  return 0;
}

Teraz działa dobrze. Kompilator tworzy tymczasowy A i użyj go, aby zadzwonić f.

Dlaczego jest A(a) różni się w obu kontekstach? Jak jest określona w standardzie lub z jakiegoś niejasnego powodu? Jak mogę utworzyć tymczasowy obiekt jak w pierwszym przykładzie kodu?


14
2018-05-13 08:50


pochodzenie


Nadal musisz nadać mu nazwę. Próbować A temp(a);. - jakber
Czy próbowałeś użyć? A{a}; w pierwszym przykładzie, ponieważ jest to przykład najbardziej irytującej analizy? Możesz także spróbować użyć void-cast: static_cast<void>(A(a)); - myaut
@jakber Chcę temp zniszczyć natychmiast po tym stwierdzeniu. To się nie stanie, jeśli nadaję mu nazwę. - Hot.PxL
jakber: nie, to istniałby do końca zakresu. Hot Pxl chce, aby to się zniszczyło na końcu instrukcji. - gpvos
Zauważ, że działa, jeśli użyjesz numeru do zainicjowania Ai że jest błąd w redefinicji a, jeśli umieścisz int a; wewnątrz głównej. - Arnon Zilca


Odpowiedzi:


Jest to kolejna instancja zasady "wszystko, co może być deklaracją jest deklaracją". [stmt.ambig] / p1:

W gramatyce występuje niejednoznaczność wyrażenie-wyrażenias   i deklaracje: wyrażenie-wyrażenia ze stylem funkcji   jawna konwersja typów (5.2.3), ponieważ może to być najbardziej lewe podwyrażenie   nie do odróżnienia od deklaracja gdzie pierwszy deklarator   zaczyna się od a (. W takich przypadkach komunikat jest deklaracja.

Standard zawiera następujące przykłady:

Zakładając, że T jest a typ prosty,

T(a)->m = 7;       // expression-statement
T(a)++;            // expression-statement
T(a,5)<<c;         // expression-statement
T(*d)(int);        // declaration
T(e)[5];           // declaration
T(f) = { 1, 2 };   // declaration
T(*g)(double(3));  // declaration

W ostatnim przykładzie powyżej g, który jest wskaźnikiem do T, jest inicjowany   do double(3). Jest to oczywiście źle sformułowane ze względów semantycznych, ale   to nie ma wpływu na analizę składniową.

i również:

class T {
// ...
public:
    T();
    T(int);
    T(int, int);
};

T(a);          // declaration
T(*b)();       // declaration
T(c)=7;        // declaration
T(d),e,f=3;    // declaration
extern int h;
T(g)(h,2);     // declaration

Najprostszym sposobem uniknięcia dwuznaczności jest prawdopodobnie dodatkowy zestaw nawiasów. (A(a)); jednoznacznie jest wyrażenie-wyrażenia.


19
2018-05-13 09:02



Myślę, że ta odpowiedź byłaby lepsza, gdyby zawierała słowa kluczowe "najbardziej irytujące parse", prawdopodobnie z linkiem do Wikipedii. - Fabio Turati
a co z A {a}; ? - paulm


Nie mogłem wymyślić sposobu na stworzenie tymczasowego bez użycia go w jakimś połączeniu, tak jak w przypadku funkcji.

Dlaczego zamiast tego nie chcesz utworzyć nazwanej zmiennej? Cykl życia będzie dokładnie taki sam, jak "tymczasowy", biorąc pod uwagę sposób, w jaki próbujesz go zadeklarować.

Jeśli naprawdę chcesz kontrolować niszczenie swojego obiektu, możesz zawsze zamknąć go w bloku: { A tmp(a); } // temporary A object


Chodzi o to ... Nie widzę sensu tego. Dlaczego chcesz utworzyć tymczasowy obiekt bez jego używania? Zazwyczaj oznacza to, że tworzenie lub destrukcja obiektu ma pewne efekty uboczne, które chcesz wywołać. To naprawdę zły pomysł! Powinieneś przenieść efekty uboczne do funkcji i po prostu ją wywołać.


4
2018-05-13 08:59



Masz rację, że powinienem użyć funkcji. Byłem tylko ciekawy, dlaczego tymczasowy nie może działać. Mam pomysł z jakiegoś kodu RTTI. Ale myślę, że to zły pomysł. - Hot.PxL