Cho dù cố ý hay vô tình, bạn có <<ở cuối dòng đầu ra đầu tiên, nơi bạn có thể có nghĩa ;. Vì vậy, về cơ bản bạn có
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
Vì vậy, câu hỏi sôi nổi về vấn đề này: tại sao cout << cout;in "1"?
Điều này hóa ra, có lẽ đáng ngạc nhiên, tinh tế. std::cout, thông qua lớp cơ sở của nó std::basic_ios, cung cấp một toán tử chuyển đổi loại nhất định được sử dụng trong bối cảnh boolean, như trong
while (cout) { PrintSomething(cout); }
Đây là một ví dụ khá tệ, vì rất khó để đầu ra thất bại - nhưng std::basic_iosthực sự là một lớp cơ sở cho cả luồng đầu vào và đầu ra, và đối với đầu vào, nó có ý nghĩa hơn nhiều:
int value;
while (cin >> value) { DoSomethingWith(value); }
(thoát khỏi vòng lặp ở cuối luồng hoặc khi các ký tự luồng không tạo thành số nguyên hợp lệ).
Bây giờ, định nghĩa chính xác của toán tử chuyển đổi này đã thay đổi giữa các phiên bản C ++ 03 và C ++ 11 của tiêu chuẩn. Trong các phiên bản cũ hơn, nó operator void*() const;(thường được triển khai dưới dạng return fail() ? NULL : this;), trong khi ở phiên bản mới hơn explicit operator bool() const;(thường được triển khai đơn giản như return !fail();). Cả hai khai báo hoạt động tốt trong bối cảnh boolean, nhưng hành xử khác nhau khi (mis) được sử dụng bên ngoài bối cảnh đó.
Cụ thể, theo quy tắc C ++ 03, cout << coutsẽ được hiểu là cout << cout.operator void*()và in một số địa chỉ. Theo quy tắc C ++ 11, hoàn toàn cout << coutkhông nên biên dịch, vì toán tử được khai báo explicitvà do đó không thể tham gia vào các chuyển đổi ngầm định. Trên thực tế, đó là động lực chính cho sự thay đổi - ngăn chặn mã vô nghĩa biên dịch. Một trình biên dịch tuân theo một trong hai tiêu chuẩn sẽ không tạo ra một chương trình in "1".
Rõ ràng, một số triển khai C ++ nhất định cho phép trộn và kết hợp trình biên dịch và thư viện theo cách tạo ra kết quả không phù hợp (trích dẫn @StephanLechner: "Tôi đã tìm thấy một cài đặt trong xcode tạo 1 và một cài đặt khác mang lại địa chỉ: Phương ngữ ngôn ngữ c ++ 98 kết hợp với "Thư viện chuẩn libc ++ (Thư viện chuẩn LLVM có hỗ trợ c ++ 11)" mang lại 1, trong khi c ++ 98 kết hợp với libstdc (thư viện chuẩn gnu c ++) mang lại địa chỉ; "). Bạn có thể có trình biên dịch kiểu C ++ 03 không hiểu explicittoán tử chuyển đổi (mới trong C ++ 11) kết hợp với thư viện kiểu C ++ 11 xác định chuyển đổi là operator bool(). Với sự pha trộn như vậy, nó có thể cout << coutđược hiểu là cout << cout.operator bool(), mà lần lượt chỉ đơn giản là cout << truevà in "1".
;ở cuối dòng đầu ra đầu tiên, không<<. Bạn không in những gì bạn nghĩ bạn đang in. Bạn đang làmcout << cout, mà in1(nó sử dụngcout.operator bool(), tôi nghĩ). Sau đó5(từ2+3) ngay lập tức theo sau, làm cho nó trông giống như số mười lăm.