Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Thuộc tính (Attributes) trong C++


Thuộc tính là cách hiện đại trong C++ để chuẩn hóa các thứ nếu mã của họ chạy trên các trình biên dịch khác nhau. Thuộc tính được dùng để cung cấp thêm thông tin được dùng để thực thi điều kiện (ràng buộc), tối ưu hóa và sinh mã cụ thể nếu cần.

Chúng giống như một sổ tay thông tin cho trình biên dịch để thực thi một số việc sẽ cải thiện hiệu suất mã. Thuộc tính xuất hiện lần đầu trong C++ 11 và là các phần quan trọng của ngôn ngữ lập trình từ đó, cũng với mỗi phiên bản, một số sửa đổi liên tục được thực hiện để làm cho chúng mạnh mẽ và tốt hơn.

Hãy xem cách định nghĩa thuộc tính trong C++

Đối với các phiên bản C++ khác nhau, cú pháp định nghĩa thuộc tính là khác nhau.

Cú pháp tạo thuộc tính trong C++ 11:

[[attribute-list]]

Cú pháp tạo thuộc tính trong C++ 17:

[[using attribute-namespace : attribute_list]]

Cú pháp tạo thuộc tính trong C++ 20 (sẽ công bố sớm):

[[contract-attriubute-token contract-level-identifier : expression]]

Bạn có thể sử dụng nhiều thuộc tính với biến, hàm, lớp.

Bây giờ, vì chúng ta đã biết thuộc tính là gì, cách chúng hoạt động và cách định nghĩa chúng. Hãy xem các thuộc tính tiêu chuẩn khác nhau có sẵn trong C++.

Thuộc tính giới thiệu trong C++ 11

noreturn - Thuộc tính này dùng để báo cho trình biên dịch biết rằng hàm không trả về bất kỳ giá trị nào.

Cú pháp

[[noreturn]] 

ví dụ

[[noreturn]] void f();

Hàm này sẽ không trả về bất kỳ giá trị nào, kể cả void.

Thuộc tính noreturn, khi dùng trong C++, cho phép trình biên dịch đưa ra cảnh báo trong trường hợp có lỗi xảy ra và luồng không quay lại mã gọi, như trong trường hợp vòng lặp vô tận hoặc bất kỳ lỗi nào.

carries_dependency - Điều này dùng để định nghĩa tất cả các phụ thuộc trong release-consume và cho phép trình biên dịch tối ưu bằng cách không đi qua các lệnh tiêu tốn bộ nhớ không cần thiết.

Cú pháp

[[carries_dependency]]

Điều này chủ yếu dùng với khai báo hàm hoặc tham số để khai báo phụ thuộc.

deprecated - Điều này dùng để định nghĩa một thực thể lỗi thời trong mã. Việc sử dụng thực thể lỗi thời này được phép nhưng không khuyến khích sử dụng.

Cú pháp

[[deprecated]] [[deprecated (reason)]]

Lý do là một chuỗi cho biết lý do lỗi thời được thực hiện và cũng cung cấp một thay thế cho thực thể lỗi thời.

Các thực thể có thể bị lỗi thời là lớp, cấu trúc, union, typedef-name, thành viên tĩnh, hàm, namespace, liệt kê.

fallthrough - Điều này dùng để báo cho trình biên dịch biết rằng việc fallthrough sang case tiếp theo là cố ý, do đó trình biên dịch không cảnh báo fallthrough.

Cú pháp

[[fallthrough]]

Fallthrough chỉ có thể dùng với switch vì case tiếp theo được định nghĩa cho nó.

nodiscard - Điều này dùng cho hàm sẽ trả về một liệt kê sẽ được gọi từ biểu thức giá trị bị loại bỏ thay vì cast sang void. Trình biên dịch cũng sẽ đưa ra cảnh báo cho nó.

Cú pháp

[[nodiscard]] [[nodiscard (reason)]] (được thêm trong C++ 20)

Lý do là một chuỗi dùng để cung cấp lý do không loại bỏ kết quả và điều này sẽ được đưa vào C++ 20.

maybe_unused - Điều này dùng để báo cho trình biên dịch tắt hoặc loại bỏ cảnh báo hiển thị trong trường hợp thực thể không sử dụng.

Cú pháp

[[maybe_unused]]

Các thực thể có thể khai báo maybe_unused là lớp, cấu trúc, union, typedef-name, thành viên tĩnh, hàm, biến, liệt kê.

likely, unlikely - Những điều này dùng để định nghĩa xem đường dẫn thay thế có khả năng xảy ra hơn hay kém hơn đường dẫn thực thi hiện tại.

Cú pháp

[[likely]] [[unlikely]]

Chúng thường được áp dụng cho các thực thể thay đổi luồng chương trình như nhãn và câu lệnh.

no_unique_address - Điều này dùng để định nghĩa một thành viên dữ liệu không cần có địa chỉ cụ thể. Nó thường dùng trong trường hợp các thành viên dữ liệu không tĩnh định nghĩa việc cấp phát bộ nhớ của chúng không cần thiết.

Cú pháp

[[no_unique_address]]

Điều này hữu ích khi trình biên dịch cần gán vị trí bộ nhớ giữa một biến bình thường và biến no_unique_address, trình biên dịch sẽ ưu tiên cái trước.

Optimize_for_synchronized - Điều này dùng để định nghĩa rằng định nghĩa hàm đã cho phải được tối ưu hóa để gọi từ câu lệnh synchronized.

Cú pháp

[[optimize_for_synchronized]]

Hàm được định nghĩa là optimize_for_synchronized sẽ tránh tuần tự hóa các khối synchronized.

expects - Nó chỉ định các điều kiện bắt buộc cho các đối số của một hàm để hàm được thực thi.

Cú pháp

[[expects : condition]] 

Điều kiện định nghĩa một điều kiện phải được thỏa mãn để hàm được thực thi.

Đây là tất cả các thuộc tính được định nghĩa trong C++ từ C++ 11 đến C++ 20. Bây giờ, hãy xem tại sao các thuộc tính này được dùng trong lập trình, tức là các thuộc tính được đề xuất giải quyết vấn đề gì?

  • Để thêm ràng buộc vào mã - Trong nhiều trường hợp, thuộc tính thêm ý nghĩa cho mã và làm cho nó hợp lệ hơn và giảm bớt công sức thừa.

  • Cung cấp thêm thông tin tối ưu hóa cho trình biên dịch - Một số thuộc tính như fallthrough, likely, maybe_used cung cấp thông tin cho trình biên dịch để thực hiện các tối ưu hóa cụ thể.

  • Tránh cảnh báo và lỗi - Đôi khi logic của lập trình viên đi ngược lại các quy tắc nghiêm ngặt của C++. Đây là trường hợp một số thuộc tính phát huy tác dụng và giúp người dùng tránh hoặc tắt các cảnh báo sẽ xảy ra.