Czy celowo, czy przypadkowo, masz <<na końcu pierwszego wiersza wyjścia, gdzie prawdopodobnie miałeś na myśli ;. Więc zasadniczo masz
cout << "2+3 = "; // this, of course, prints "2+3 = "
cout << cout; // this prints "1"
cout << 2 + 3; // this prints "5"
cout << endl; // this finishes the line
A więc pytanie sprowadza się do tego: dlaczego cout << cout;druk "1"?
Okazuje się to, być może zaskakująco, subtelne. std::cout, poprzez swoją klasę bazową std::basic_ios, zapewnia pewien operator konwersji typu, który jest przeznaczony do użycia w kontekście logicznym, jak w
while (cout) { PrintSomething(cout); }
To dość kiepski przykład, ponieważ trudno jest doprowadzić do niepowodzenia wyjścia - ale w std::basic_iosrzeczywistości jest to klasa bazowa zarówno dla strumieni wejściowych, jak i wyjściowych, a dla danych wejściowych ma znacznie więcej sensu:
int value;
while (cin >> value) { DoSomethingWith(value); }
(wychodzi z pętli na końcu strumienia lub gdy znaki strumienia nie tworzą prawidłowej liczby całkowitej).
Teraz dokładna definicja tego operatora konwersji została zmieniona między wersjami standardu C ++ 03 i C ++ 11. W starszych wersjach był operator void*() const;(zwykle implementowany jako return fail() ? NULL : this;), podczas gdy w nowszych jest explicit operator bool() const;(zwykle implementowany po prostu jako return !fail();). Obie deklaracje działają dobrze w kontekście logicznym, ale zachowują się inaczej, gdy (niewłaściwie) są używane poza tym kontekstem.
W szczególności, zgodnie z regułami C ++ 03, cout << coutzostanie zinterpretowany jako cout << cout.operator void*()i wypisze jakiś adres. Zgodnie z regułami C ++ 11 cout << coutnie powinien w ogóle kompilować, ponieważ operator jest zadeklarowany, explicita zatem nie może uczestniczyć w niejawnych konwersjach. To była w istocie główna motywacja do zmiany - zapobieżenie kompilacji bezsensownego kodu. Kompilator zgodny z żadnym standardem nie utworzyłby programu, który drukuje "1".
Najwyraźniej niektóre implementacje C ++ pozwalają na miksowanie i dopasowywanie kompilatora i biblioteki w sposób, który daje niezgodny wynik (cytując @StephanLechner: „Znalazłem ustawienie w xcode, które daje 1, i inne ustawienie, które daje adres: Dialekt języka c ++ 98 w połączeniu z "Biblioteka standardowa libc ++ (biblioteka standardowa LLVM z obsługą c ++ 11)" daje 1, podczas gdy c ++ 98 w połączeniu z libstdc (biblioteka standardowa gnu c ++) daje adres; "). Możesz mieć kompilator w stylu C ++ 03, który nie rozumie explicitoperatorów konwersji (które są nowe w C ++ 11) w połączeniu z biblioteką w stylu C ++ 11, która definiuje konwersję jako operator bool(). Z taką mieszanką staje się możliwe cout << coutzinterpretowanie jako cout << cout.operator bool(), co z kolei jest proste cout << truei drukuje "1".
;na końcu pierwszego wiersza wyjścia, a nie<<. Nie drukujesz tego, co myślisz, że drukujesz. Robiszcout << cout, co drukuje1(cout.operator bool()chyba używa ). Następnie5(od2+3) następuje natychmiast, dzięki czemu wygląda jak liczba piętnaście.