Một phương pháp đẹp:
#ifdef _DEBUG
#define DBOUT cout // or any other ostream
#else
#define DBOUT 0 && cout
#endif
DBOUT << "This is a debug build." << endl;
DBOUT << "Some result: " << doSomething() << endl;
Chừng nào bạn không làm bất cứ điều gì lạ, chức năng gọi và truyền cho DBOUT
sẽ không được gọi trong phiên bản xây dựng. Macro này hoạt động vì ưu tiên toán tử và logic AND; bởi vì &&
có mức ưu tiên thấp hơn <<
, hãy xây dựng bản dựng biên dịch DBOUT << "a"
là 0 && (cout << "a")
. Logic AND không đánh giá biểu thức ở bên phải nếu biểu thức bên trái đánh giá về 0 hoặc false
; bởi vì biểu thức bên tay trái luôn luôn đánh giá bằng không, biểu thức bên phải luôn bị xóa bởi bất kỳ trình biên dịch nào đáng sử dụng trừ khi tất cả tối ưu hóa bị tắt (và thậm chí sau đó, mã rõ ràng không thể truy cập vẫn có thể bị bỏ qua.)
Dưới đây là một ví dụ về những điều kỳ lạ rằng sẽ phá vỡ macro này:
DBOUT << "This is a debug build." << endl, doSomething();
Watch dấu phẩy. doSomething()
sẽ luôn được gọi, bất kể có hay không _DEBUG
được xác định. Điều này là do báo cáo kết quả được đánh giá trong phiên bản xây dựng như:
(0 && (cout << "This is a debug build." << endl)), doSomething();
// evaluates further to:
false, doSomething();
Để sử dụng dấu phẩy với macro này, dấu phẩy phải được bọc trong dấu ngoặc đơn, như vậy:
DBOUT << "Value of b: " << (a, b) << endl;
Một ví dụ khác:
(DBOUT << "Hello, ") << "World" << endl; // Compiler error on release build
Trong bản xây dựng bản phát hành, điều này được đánh giá là:
(0 && (cout << "Hello, ")) << "World" << endl;
// evaluates further to:
false << "World" << endl;
gây ra lỗi trình biên dịch vì không thể chuyển đổi bool
sang trái bởi con trỏ char
trừ khi toán tử tùy chỉnh được xác định. Cú pháp này cũng gây ra vấn đề bổ sung:
(DBOUT << "Result: ") << doSomething() << endl;
// evaluates to:
false << doSomething() << endl;
Giống như khi các dấu phẩy được sử dụng kém, doSomething()
vẫn được gọi, bởi vì kết quả của nó đã được chuyển tới các nhà điều hành trái ca. (Điều này chỉ có thể xảy ra khi một nhà điều hành tùy chỉnh được định nghĩa rằng trái chuyển một bool
bởi một con trỏ char
;. Nếu không, một lỗi biên dịch xảy ra)
Đừng nghĩ giải lao DBOUT << ...
. Nếu bạn muốn ngoặc đơn một số nguyên thay đổi, sau đó ngoặc đơn nó, nhưng tôi không biết một lý do chính đáng để ngoặc đơn một toán tử luồng.
Cảm ơn! Tôi bắt đầu tự nghĩ ra điều gì đó dọc theo những dòng này và tôi rất vui khi thấy tôi không phải là người duy nhất nghĩ về nó. Tôi sẽ thử nó vào thứ hai trở lại tại nơi làm việc và xem như thế nào trình biên dịch có thể tối ưu hóa dòng đi. – Emanuel
Bất kỳ ai sử dụng phương pháp này, xin lưu ý rằng một số mục sẽ không được tối ưu hóa trong chế độ phát hành. Nếu bạn có: '' 'debug << someCPUIntensiveFunctionOrFunctionWhichMayAffectState() <<" \ n "' '' nó sẽ vẫn chạy trong chế độ phát hành. Tôi đã bỏ lỡ cavet này lần đầu tiên trong vòng –