Chuyển đổi ngầm định sang bool
Vấn đề
Phần tiêu đề “Vấn đề”C++ tự động chuyển đổi nhiều kiểu dữ liệu sang bool trong ngữ cảnh điều kiện (if, while, &&, ||…) - điều này tiện lợi nhưng cũng là nguồn gốc của nhiều lỗi tinh vi nếu không để ý.
Số 0 luôn là false, mọi số khác 0 đều là true
Phần tiêu đề “Số 0 luôn là false, mọi số khác 0 đều là true”int code = -1;
if (code) { // -1 khác 0, nên đây là TRUE - có thể không phải điều bạn nghĩ! std::cout << "Duoc coi la dung, du code la -1" << std::endl;}Đây là cạm bẫy phổ biến khi một hàm trả về mã lỗi (error code): quy ước thường là 0 nghĩa là “thành công”, khác 0 nghĩa là “có lỗi” - ngược lại với trực giác if (result):
int result = run_command(); // Giả sử: 0 = thành công, khác 0 = mã lỗi
if (result) { // SAI Ý ĐỊNH! Đoạn này chạy khi CÓ LỖI (result != 0), không phải khi thành công std::cout << "Thanh cong?" << std::endl; // Nhầm lẫn logic}
if (result == 0) { // ĐÚNG - kiểm tra tường minh, rõ ràng ý định std::cout << "Thanh cong" << std::endl;}Con trỏ cũng chuyển đổi ngầm định sang bool
Phần tiêu đề “Con trỏ cũng chuyển đổi ngầm định sang bool”int* ptr = get_pointer(); // Có thể trả về nullptr
if (ptr) { // Tương đương if (ptr != nullptr) - đây là cách viết phổ biến, không phải lỗi std::cout << *ptr << std::endl;}
if (!ptr) { // Tương đương if (ptr == nullptr) std::cout << "Con tro rong" << std::endl;}Cách viết if (ptr) là hợp lệ và phổ biến, nhưng cần chắc chắn ptr thực sự mang ý nghĩa “có tồn tại hay không”, không phải một con trỏ luôn được kỳ vọng hợp lệ (trường hợp đó nên dùng assert hoặc kiểm tra tường minh hơn).
Con trỏ smart pointer cũng vậy
Phần tiêu đề “Con trỏ smart pointer cũng vậy”#include <memory>
std::unique_ptr<int> ptr = std::make_unique<int>(42);
if (ptr) { // Kiểm tra ptr có đang quản lý một đối tượng hay không std::cout << *ptr << std::endl;}Cạm bẫy: nhầm = và == càng nguy hiểm hơn với chuyển đổi ngầm định
Phần tiêu đề “Cạm bẫy: nhầm = và == càng nguy hiểm hơn với chuyển đổi ngầm định”int flag = 0;
if (flag = 5) { // GÁN, không phải so sánh - 5 khác 0 nên LUÔN đúng! std::cout << "Luon chay vao day" << std::endl; // Lỗi logic nghiêm trọng}Đã đề cập ở bài “Thứ tự ưu tiên toán tử” - kết hợp với chuyển đổi ngầm định sang bool, lỗi gõ nhầm =/== trở nên đặc biệt khó phát hiện vì code vẫn biên dịch và “chạy được”.
Tóm tắt
Phần tiêu đề “Tóm tắt”C++ tự động chuyển
0/con trỏ null thànhfalse, mọi giá trị khác thànhtruetrong ngữ cảnh điều kiện.
- Cẩn thận với các hàm trả về mã lỗi kiểu C (
0= thành công) -if (result)dễ bị hiểu ngược ý định- Luôn viết điều kiện tường minh (
if (result == 0)) khi ý nghĩa của giá trị số không hiển nhiên là true/false- Bật cảnh báo trình biên dịch để bắt lỗi gõ nhầm
=thành==