Problem jest to, że kompilator interpretuje
test(_b);
Nie jako kodu, który tworzy tymczasowy obiekt typu test
przechodzącą w parametrze _b
, ale jako zmienna deklaracji zmiennej o nazwie _b
typu test
, stosując domyślny konstruktor. W związku z tym, co wygląda jak fragment kodu, który tworzy tymczasowy obiekt test
przy użyciu drugiego konstruktora, rekursywnie tworzy nowy obiekt typu test
i wywołuje konstruktora w innym czasie.
Aby rozwiązać ten problem, można nadać zmiennej jednoznacznej nazwy, takie jak
test t(_b);
ten można interpretować jedynie jako zmienna typu test
nazwie t
, zainicjowana przy użyciu drugiego konstruktora.
Mam nigdy widziałem to wcześniej, a ja programowałem w C++ od lat. Dzięki za pokazanie mi kolejnej narożnej wersji języka!
Oficjalne wyjaśnienie: zgodnie ze specyfikacją ISO C++ 03, § 6.8:
Jest dwuznaczność w gramatyce udziałem ekspresję wypowiedzi i deklaracje: Wyrażenie-sprawozdanie z funkcją konwersji stylu jawne typu (5.2.3) jako skrajny lewy podwyrażenie może być nie do odróżnienia od deklaracji gdzie pierwszy declarator zaczyna się od (. W tych przypadkach oświadczenie jest oświadczeniem.
(Moje podkreślenie). innymi słowy, za każdym razem, C++ mógłby zinterpretować oświadczenie albo jako wyraz (tymczasowego obiektu obsadzie) lub jako deklaracja (zmiennej), wybierze deklarację. Specyfikacja C++ jawnie daje
T (a);
Jako przykład deklaracji, a nie odlewania a
na coś typu T
.
To jest C++ 's Most Vexing Parse - to, co wygląda na wyrażenie, jest zamiast tego interpretowane jako deklaracja. Widziałem już wcześniej MVP, ale nigdy nie widziałem go w tym kontekście.
Mam nadzieję, że to pomoże!
To rekursja ze względu na 'test (_b);' ale nie jestem pewien, dlaczego. – Roddy
@ Roddy - Właśnie to rozgryzłem; zobacz moją odpowiedź po szczegóły. – templatetypedef
Oczyszczona wersja z nieistotnymi usuniętymi materiałami: http://ideone.com/z0yc7Q – Yakk