Baik disengaja atau tidak, Anda memiliki <<
di akhir garis output pertama, di mana Anda mungkin dimaksudkan ;
. Jadi pada dasarnya Anda memilikinya
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
Jadi pertanyaannya bermuara pada ini: mengapa cout << cout;
cetak "1"
?
Ini ternyata, mungkin mengejutkan, halus. std::cout
, melalui kelas dasarnya std::basic_ios
, menyediakan operator konversi tipe tertentu yang dimaksudkan untuk digunakan dalam konteks boolean, seperti pada
while (cout) { PrintSomething(cout); }
Ini adalah contoh yang sangat buruk, karena sulit untuk mendapatkan output gagal - tetapi std::basic_ios
sebenarnya adalah kelas dasar untuk input dan output stream, dan untuk input itu jauh lebih masuk akal:
int value;
while (cin >> value) { DoSomethingWith(value); }
(keluar dari loop di ujung aliran, atau ketika karakter aliran tidak membentuk bilangan bulat yang valid).
Sekarang, definisi pasti dari operator konversi ini telah berubah antara versi standar C ++ 03 dan C ++ 11. Di versi yang lebih lama, itu operator void*() const;
(biasanya diimplementasikan sebagai return fail() ? NULL : this;
), sedangkan di versi yang lebih baru explicit operator bool() const;
(biasanya diimplementasikan sebagai return !fail();
) Kedua deklarasi berfungsi dengan baik dalam konteks boolean, tetapi berperilaku berbeda ketika (mis) digunakan di luar konteks tersebut.
Secara khusus, di bawah aturan C ++ 03, cout << cout
akan ditafsirkan sebagai cout << cout.operator void*()
dan mencetak beberapa alamat. Di bawah aturan C ++ 11, cout << cout
tidak boleh dikompilasi sama sekali, karena operator dinyatakan explicit
dan karenanya tidak dapat berpartisipasi dalam konversi tersirat. Itu sebenarnya adalah motivasi utama untuk perubahan - mencegah penyusunan kode yang tidak masuk akal. Kompiler yang sesuai dengan standar mana pun tidak akan menghasilkan program yang mencetak "1"
.
Rupanya, implementasi C ++ tertentu memungkinkan pencampuran dan pencocokan kompiler dan perpustakaan sedemikian rupa sehingga menghasilkan hasil yang tidak sesuai (mengutip @StephanLechner: "Saya menemukan pengaturan dalam xcode yang menghasilkan 1, dan pengaturan lain yang menghasilkan alamat: Dialek bahasa c ++ 98 dikombinasikan dengan "Perpustakaan standar libc ++ (perpustakaan standar LLVM dengan dukungan c ++ 11)" menghasilkan 1, sedangkan c ++ 98 dikombinasikan dengan libstdc (gnu c ++ perpustakaan standar) menghasilkan alamat; "). Anda dapat memiliki kompiler gaya C ++ 03 yang tidak memahami explicit
operator konversi (yang baru dalam C ++ 11) dikombinasikan dengan pustaka gaya C ++ 11 yang mendefinisikan konversi sebagai operator bool()
. Dengan campuran seperti itu, menjadi mungkin untuk cout << cout
diartikan sebagai cout << cout.operator bool()
, yang pada gilirannya sederhana cout << true
dan dicetak "1"
.
;
di akhir garis output pertama, bukan<<
. Anda tidak mencetak apa yang menurut Anda dicetak. Anda lakukancout << cout
, yang mencetak1
(menggunakancout.operator bool()
, saya pikir). Kemudian5
(dari2+3
) langsung mengikuti, membuatnya tampak seperti angka lima belas.