Standard Attributes (Các thuộc tính chuẩn hóa)
Standard Attributes là cú pháp dạng [[...]]
được chuẩn hóa trong C++ nhằm cung cấp thêm thông tin cho trình biên dịch mà không ảnh hưởng đến logic chương trình. Chúng giúp cải thiện khả năng tối ưu, tăng độ rõ ràng và hỗ trợ phát hiện lỗi sớm khi biên dịch.
Trang này liệt kê các thuộc tính phổ biến như [[nodiscard]]
, [[maybe_unused]]
, [[deprecated]]
... kèm ví dụ, lợi ích và lưu ý sử dụng.
Ghi nhớ: Các attribute không thay đổi hành vi chương trình nếu dùng đúng, nhưng có thể dẫn đến undefined behavior nếu lạm dụng (như [[assume]]
). Hãy sử dụng một cách có hiểu biết.
C++11
[[noreturn]]
- Ý nghĩa: Chỉ định rằng hàm không bao giờ trả về điều khiển cho nơi gọi (thường dùng cho hàm thoát chương trình
exit()
hoặc ném ngoại lệthrow
). - Ví dụ:
[[noreturn]] void fatal_error() {
std::exit(1); // Không bao giờ return
} - Lợi ích: Giúp trình biên dịch tối ưu hóa mã, kiểm soát luồng tốt hơn và cảnh báo nếu có mã không thể truy cập sau lời gọi hàm.
- Ý nghĩa: Chỉ định rằng hàm không bao giờ trả về điều khiển cho nơi gọi (thường dùng cho hàm thoát chương trình
C++14
[[deprecated]]
- Ý nghĩa: Cảnh báo lập trình viên khi sử dụng thực thể được đánh dấu, giúp khuyến khích chuyển sang API hoặc phương pháp thay thế. Không ngăn cản biên dịch, chỉ tạo cảnh báo (warning).
- Cú pháp:
[[deprecated("Use new_function() instead")]]
void old_function() { /* ... */ }- Có thể kèm theo một thông điệp tùy chọn (chuỗi) để giải thích lý do hoặc gợi ý thay thế.
- Ví dụ:
#include <iostream>
[[deprecated("Use modern_print() instead")]]
void old_print() {
std::cout << "Old print function\n";
}
void modern_print() {
std::cout << "Modern print function\n";
}
int main() {
old_print(); // Trình biên dịch sẽ cảnh báo
modern_print();
return 0;
} - Ứng dụng: Sử dụng khi bạn muốn đánh dấu mã cũ trong dự án, chẳng hạn khi nâng cấp thư viện hoặc chuyển sang API mới.
C++17
-
[[nodiscard]]
- Ý nghĩa: Báo rằng giá trị trả về của hàm không nên bị bỏ qua. Nếu bỏ qua, trình biên dịch tạo cảnh báo.
- Ví dụ:
[[nodiscard]] int compute() { return 42; }
int main() {
compute(); // Cảnh báo: bỏ qua giá trị trả về
return 0;
} - Lợi ích: Ngăn lỗi logic khi lập trình viên vô tình bỏ qua kết quả quan trọng. Tránh bỏ qua giá trị quan trọng như
error code
,std::unique_ptr
.
-
[[maybe_unused]]
- Ý nghĩa: Ngăn cảnh báo về biến hoặc tham số không sử dụng.
- Ví dụ:
void func([[maybe_unused]] int x) { /* Không dùng x */ }
- Lợi ích: Giảm cảnh báo thừa, đặc biệt trong debug/test.
-
[[fallthrough]]
- Ý nghĩa: Chỉ định rằng việc "rơi qua" (fall through) trong một
switch-case
là cố ý, ngăn cảnh báo-Wimplicit-fallthrough
. - Ví dụ:
switch (value) {
case 1:
std::cout << "Case 1\n";
[[fallthrough]];
case 2:
std::cout << "Case 2\n";
break;
} - Lợi ích: Làm rõ ý định của lập trình viên, tránh nhầm lẫn.
- Ý nghĩa: Chỉ định rằng việc "rơi qua" (fall through) trong một
C++20
-
[[likely]]
và[[unlikely]]
- Ý nghĩa: Gợi ý cho trình biên dịch rằng một nhánh trong câu lệnh điều kiện (if, switch) có khả năng xảy ra nhiều (
[[likely]]
) hoặc ít ([[unlikely]]
) hơn, giúp tối ưu hóa hiệu suất. - Ví dụ:
if (condition) [[likely]] {
// Xử lý trường hợp phổ biến
} else [[unlikely]] {
// Xử lý trường hợp hiếm
} - Lợi ích: Hỗ trợ trình biên dịch tạo mã máy hiệu quả hơn (ví dụ: sắp xếp nhánh trong CPU pipeline).
- Ý nghĩa: Gợi ý cho trình biên dịch rằng một nhánh trong câu lệnh điều kiện (if, switch) có khả năng xảy ra nhiều (
-
[[no_unique_address]]
- Ý nghĩa: Cho phép trình biên dịch tối ưu hóa bố trí bộ nhớ của một thành viên dữ liệu trong lớp/struct, đặc biệt khi thành viên đó có thể không chiếm không gian (empty type).
- Ví dụ:
struct Empty {};
struct Data {
[[no_unique_address]] Empty e;
int value;
}; - Lợi ích: Giảm kích thước của struct nếu
Empty
không cần địa chỉ riêng, tối ưu bộ nhớ.
C++23
[[assume]]
- Ý nghĩa: Cho phép lập trình viên cung cấp giả định (assumption) về giá trị hoặc điều kiện để trình biên dịch tối ưu hóa mã, nhưng không kiểm tra tại runtime. Gợi ý cho compiler rằng
condition
luôn đúng tại thời điểm đó. - Ví dụ:
void process(int* ptr) {
[[assume(ptr != nullptr)]];
*ptr = 42; // Trình biên dịch giả định ptr hợp lệ
} - Lợi ích: Tăng hiệu suất bằng cách loại bỏ kiểm tra dư thừa.
- Lưu ý nguy hiểm: Nếu
condition
không đúng tại runtime, undefined behavior xảy ra! Chỉ dùng khi chắc chắn.
- Ý nghĩa: Cho phép lập trình viên cung cấp giả định (assumption) về giá trị hoặc điều kiện để trình biên dịch tối ưu hóa mã, nhưng không kiểm tra tại runtime. Gợi ý cho compiler rằng