Vì vậy, câu hỏi của tôi là thế này - nếu ném từ một hàm hủy dẫn đến hành vi không xác định, làm thế nào để bạn xử lý các lỗi xảy ra trong một hàm hủy?
Vấn đề chính là đây: bạn không thể thất bại . Rốt cuộc có nghĩa là gì khi thất bại? Nếu việc giao dịch với cơ sở dữ liệu không thành công và thất bại (không thể khôi phục), điều gì xảy ra với tính toàn vẹn của dữ liệu của chúng tôi?
Vì các hàm hủy được gọi cho cả hai đường thông thường và ngoại lệ (thất bại), bản thân chúng không thể thất bại nếu không chúng ta "thất bại".
Đây là một vấn đề khó khăn về mặt khái niệm nhưng thường giải pháp là chỉ cần tìm một cách để đảm bảo rằng thất bại không thể thất bại. Ví dụ: cơ sở dữ liệu có thể ghi các thay đổi trước khi cam kết cấu trúc dữ liệu bên ngoài hoặc tệp. Nếu giao dịch thất bại, thì cấu trúc tệp / dữ liệu có thể bị loại bỏ. Tất cả những gì phải đảm bảo là cam kết những thay đổi từ cấu trúc bên ngoài đó / gửi một giao dịch nguyên tử không thể thất bại.
Giải pháp thực tế có lẽ chỉ cần đảm bảo rằng cơ hội thất bại trong thất bại là không thể thực hiện được, vì làm cho mọi thứ không thể thất bại có thể gần như không thể trong một số trường hợp.
Giải pháp phù hợp nhất với tôi là viết logic không dọn dẹp của bạn theo cách mà logic dọn dẹp không thể thất bại. Ví dụ: nếu bạn muốn tạo cấu trúc dữ liệu mới để dọn sạch cấu trúc dữ liệu hiện có, thì có lẽ bạn có thể tìm cách tạo cấu trúc phụ trợ đó trước để chúng ta không còn phải tạo cấu trúc bên trong hàm hủy.
Điều này nói thì dễ hơn nhiều so với thực hiện, nhưng đó là cách thực sự đúng đắn duy nhất tôi thấy để nói về nó. Đôi khi tôi nghĩ rằng nên có khả năng viết logic hủy diệt riêng biệt cho các đường dẫn thực thi thông thường khỏi các đường dẫn ngoại lệ, vì đôi khi các hàm hủy có cảm giác hơi giống như chúng có trách nhiệm gấp đôi bằng cách cố gắng xử lý cả hai (một ví dụ là các bộ bảo vệ phạm vi yêu cầu loại bỏ rõ ràng ; họ sẽ không yêu cầu điều này nếu họ có thể phân biệt các con đường phá hủy đặc biệt với những con đường không đặc biệt).
Vấn đề cuối cùng là chúng ta không thể thất bại và đó là một vấn đề thiết kế khái niệm khó giải quyết trong mọi trường hợp. Sẽ dễ dàng hơn nếu bạn không bị cuốn vào các cấu trúc điều khiển phức tạp với hàng tấn vật thể tuổi teen tương tác với nhau, và thay vào đó mô hình hóa các thiết kế của bạn theo kiểu hơi cồng kềnh (ví dụ: hệ thống hạt với bộ phá hủy để phá hủy toàn bộ hạt hệ thống, không phải là một hàm hủy không tầm thường riêng biệt cho mỗi hạt). Khi bạn mô hình hóa các thiết kế của mình ở mức độ thô hơn này, bạn sẽ có ít hơn các công cụ phá hủy không tầm thường để xử lý, và cũng có thể thường xuyên chi trả cho bất kỳ bộ nhớ / xử lý nào được yêu cầu để đảm bảo rằng các công cụ phá hủy của bạn không thể thất bại.
Và đó là một trong những giải pháp đơn giản nhất một cách tự nhiên là sử dụng các công cụ phá hủy ít thường xuyên hơn. Trong ví dụ về hạt ở trên, có lẽ khi phá hủy / loại bỏ hạt, một số điều nên được thực hiện có thể thất bại vì bất kỳ lý do gì. Trong trường hợp đó, thay vì gọi logic như vậy thông qua dtor của hạt có thể được thực thi trong một đường dẫn đặc biệt, thay vào đó bạn có thể thực hiện tất cả bởi hệ thống hạt khi loại bỏ hạt. Loại bỏ một hạt có thể luôn luôn được thực hiện trong một con đường không đặc biệt. Nếu hệ thống bị phá hủy, có thể nó chỉ có thể thanh lọc tất cả các hạt và không bận tâm với logic loại bỏ hạt riêng lẻ đó có thể bị lỗi, trong khi logic có thể bị hỏng chỉ được thực thi trong quá trình thực thi bình thường của hệ thống hạt khi loại bỏ một hoặc nhiều hạt.
Thường có những giải pháp như thế sẽ mọc lên nếu bạn tránh phải đối phó với nhiều đối tượng tuổi teen với những kẻ hủy diệt không tầm thường. Nơi bạn có thể bị vướng vào một mớ hỗn độn, nơi dường như không thể là ngoại lệ - an toàn là khi bạn bị vướng vào rất nhiều đồ vật tuổi teen mà tất cả đều có những kẻ không tầm thường.
Nó sẽ giúp ích rất nhiều nếu nothrow / noexcept thực sự được dịch thành lỗi trình biên dịch nếu bất cứ thứ gì chỉ định nó (bao gồm các hàm ảo sẽ kế thừa đặc tả noexcept của lớp cơ sở của nó) đã cố gắng gọi bất cứ thứ gì có thể ném. Bằng cách này, chúng ta sẽ có thể bắt được tất cả những thứ này vào thời gian biên dịch nếu chúng ta thực sự viết một hàm hủy vô tình có thể ném.