Будь то навмисно чи випадково, у вас є <<
в кінці першого рядка вихід, де ви, мабуть, мали на увазі ;
. Так ви по суті маєте
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
Тож питання зводиться до цього: чому cout << cout;
друкується "1"
?
Це виявляється, мабуть напрочуд, тонко. std::cout
через базовий клас std::basic_ios
забезпечує оператор перетворення певного типу, який призначений для використання в булевому контексті, як у
while (cout) { PrintSomething(cout); }
Це досить бідний приклад, оскільки складно отримати вихід з ладу - але std::basic_ios
насправді базовий клас як для вхідних, так і вихідних потоків, а для введення має набагато більше сенсу:
int value;
while (cin >> value) { DoSomethingWith(value); }
(виходить з циклу в кінці потоку або коли символи потоку не утворюють дійсного цілого числа).
Тепер точне визначення цього оператора перетворення змінилося між C ++ 03 та C ++ 11 версіями стандарту. У старих версіях він був operator void*() const;
(як правило, реалізований як return fail() ? NULL : this;
), а в більш нових версіях - explicit operator bool() const;
як правило, просто як return !fail();
). Обидві декларації справно працюють у булевому контексті, але поводяться по-різному, коли (неправильно) використовуються поза таким контекстом.
Зокрема, відповідно до правил C ++ 03, cout << cout
інтерпретуватимуться як cout << cout.operator void*()
та надрукувати якусь адресу. Згідно з правилами C ++ 11, cout << cout
взагалі не слід збирати компіляцію, оскільки оператор декларується explicit
і тому не може брати участь у неявних перетвореннях. Це насправді була основною мотивацією змін - запобігання безглуздого коду від компіляції. Компілятор, який відповідає будь-якому стандарту, не створював би програму, яка друкує "1"
.
Мабуть, певні реалізації C ++ дозволяють змішувати та узгоджувати компілятор та бібліотеку таким чином, що створює невідповідний результат (цитуючи @StephanLechner: "Я знайшов налаштування в xcode, який виробляє 1, та інше налаштування, яке дає адресу: Мова діалект c ++ 98 у поєднанні зі "Стандартною бібліотекою libc ++ (стандартна бібліотека LLVM з підтримкою c ++ 11)" дає 1, тоді як c ++ 98 у поєднанні з libstdc (gnu c ++ стандартна бібліотека) дає адресу; "). Ви можете мати компілятор стилю C ++ 03, який не розуміє explicit
операторів перетворення (які є новими в C ++ 11) у поєднанні з бібліотекою стилю C ++ 11, яка визначає конверсію як operator bool()
. З такою сумішшю стає можливою cout << cout
інтерпретація як cout << cout.operator bool()
, що, в свою чергу, просто cout << true
і друкує "1"
.
;
в кінці першого рядка виводу, а не<<
. Ви не друкуєте те, що думаєте, що друкуєте. Ви робитеcout << cout
, який друкує1
(він використовуєcout.operator bool()
, я думаю). Потім5
(з2+3
) негайно випливає, роблячи це схожим на число п’ятнадцять.