- Có nhiều ví dụ về các hàm mà tôi biết sẽ không bao giờ ném, nhưng trình biên dịch không thể tự xác định. Tôi có nên nối thêm ngoại lệ vào khai báo hàm trong tất cả các trường hợp như vậy không?
noexcept
là khó khăn, vì nó là một phần của giao diện chức năng. Đặc biệt, nếu bạn đang viết thư viện, mã khách hàng của bạn có thể phụ thuộc vào thuộc noexcept
tính. Có thể khó thay đổi nó sau này, vì bạn có thể phá vỡ mã hiện có. Điều đó có thể ít quan tâm hơn khi bạn triển khai mã chỉ được sử dụng bởi ứng dụng của bạn.
Nếu bạn có một chức năng không thể ném, hãy tự hỏi liệu nó sẽ thích ở lại noexcept
hay điều đó sẽ hạn chế việc thực hiện trong tương lai? Ví dụ: bạn có thể muốn giới thiệu kiểm tra lỗi đối số bất hợp pháp bằng cách đưa ra các ngoại lệ (ví dụ: đối với kiểm tra đơn vị) hoặc bạn có thể phụ thuộc vào mã thư viện khác có thể thay đổi thông số ngoại lệ của nó. Trong trường hợp đó, an toàn hơn là bảo thủ và bỏ qua noexcept
.
Mặt khác, nếu bạn tự tin rằng hàm không bao giờ nên ném và đúng là nó là một phần của đặc tả, bạn nên khai báo nó noexcept
. Tuy nhiên, hãy nhớ rằng trình biên dịch sẽ không thể phát hiện các vi phạm noexcept
nếu việc triển khai của bạn thay đổi.
- Đối với những tình huống nào tôi nên cẩn thận hơn về việc sử dụng noexcept, và trong những tình huống nào tôi có thể thoát khỏi với ẩn ý ngụ ý (sai)?
Có bốn loại chức năng mà bạn nên tập trung vào vì chúng có thể sẽ có tác động lớn nhất:
- di chuyển các hoạt động (di chuyển toán tử gán và di chuyển các nhà xây dựng)
- hoạt động hoán đổi
- bộ giải mã bộ nhớ (xóa toán tử, xóa toán tử [])
- hàm hủy (mặc dù những thứ này là ngầm
noexcept(true)
trừ khi bạn tạo ra chúng noexcept(false)
)
Các chức năng này thường là noexcept
, và rất có thể các triển khai thư viện có thể sử dụng noexcept
tài sản. Ví dụ, std::vector
có thể sử dụng các hoạt động di chuyển không ném mà không phải hy sinh các đảm bảo ngoại lệ mạnh. Nếu không, nó sẽ phải quay lại sao chép các phần tử (như đã làm trong C ++ 98).
Loại tối ưu hóa này ở cấp độ thuật toán và không dựa vào tối ưu hóa trình biên dịch. Nó có thể có một tác động đáng kể, đặc biệt là nếu các yếu tố đắt tiền để sao chép.
- Khi nào tôi thực sự có thể mong đợi quan sát sự cải thiện hiệu suất sau khi sử dụng noexcept? Cụ thể, đưa ra một ví dụ về mã mà trình biên dịch C ++ có thể tạo mã máy tốt hơn sau khi thêm noexcept.
Ưu điểm của việc noexcept
không có đặc điểm kỹ thuật ngoại lệ hoặc throw()
là tiêu chuẩn cho phép trình biên dịch tự do hơn khi nói đến ngăn xếp ngăn xếp. Ngay cả trong throw()
trường hợp, trình biên dịch phải hoàn toàn giải phóng ngăn xếp (và nó phải thực hiện theo thứ tự ngược lại chính xác của các cấu trúc đối tượng).
Trong noexcept
trường hợp, mặt khác, không bắt buộc phải làm điều đó. Không có yêu cầu rằng ngăn xếp phải được mở ra (nhưng trình biên dịch vẫn được phép làm điều đó). Sự tự do đó cho phép tối ưu hóa mã hơn nữa vì nó làm giảm chi phí luôn có thể giải phóng ngăn xếp.
Câu hỏi liên quan về không có ngoại lệ, giải nén ngăn xếp và hiệu suất đi sâu vào chi tiết hơn về chi phí khi yêu cầu ngăn xếp ngăn xếp.
Tôi cũng đề nghị cuốn sách "Hiệu quả hiện đại C ++" của Scott Meyers, "Mục 14: Khai báo các hàm không có ngoại lệ nếu chúng không phát ra ngoại lệ" để đọc thêm.
move_if_nothrow
(hoặc whatchamacallit) sẽ thấy sự cải thiện hiệu suất nếu có một ctor di chuyển không có ngoại lệ.