2010-01-07 39 views
42

Tôi thấy rằng có ba cách để bắt ngoại lệ, sự khác biệt là gì?bắt ngoại lệ bằng con trỏ trong C++

1) bắt theo giá trị;

2) bắt bằng tham chiếu;

3) bắt bằng con trỏ;

Tôi chỉ biết rằng bắt theo giá trị sẽ gọi hai bản sao của đối tượng, bắt theo tham chiếu sẽ gọi một. Vì vậy, làm thế nào về bắt bằng con trỏ? Khi nào thì sử dụng bắt bằng con trỏ? Ngoài việc ném một vật thể, tôi có thể ném một con trỏ đến một vật như thế này không?

class A {} 

void f() { 

    A *p = new A(); 
     throw p; 


} 
+6

Bạn có thể __not__ bắt ngoại lệ bằng con trỏ. Bạn có thể bắt một ngoại lệ xảy ra là một con trỏ. Vấn đề là A và A * là hai loại hoàn toàn khác nhau. Nếu bạn ném một con trỏ đến A thì bạn chỉ có thể bắt được giá trị hoặc tham chiếu. Nhưng nó là một A * mà bạn đang đánh bắt bởi giá trị hoặc tham chiếu không phải là A. –

Trả lời

70

Cách đề nghị là để ném theo giá trị và đánh bắt bằng cách tham khảo.

Mã ví dụ của bạn ném con trỏ, đó là một ý tưởng tồi vì bạn sẽ phải quản lý bộ nhớ tại trang bắt.

Nếu bạn thực sự cảm thấy bạn nên ném một con trỏ, hãy sử dụng con trỏ thông minh như shared_ptr.

Dù sao, Herb Sutter và Alexei Alexandrescu giải thích rằng thực sự tốt trong cuốn sách C++ Coding Standards mà tôi đã diễn giải.

Xem C++ Coding Standards: Throw by Value, Catch by Reference.

+12

Và nếu lý do bạn đang ném là bởi vì bạn đang hết bộ nhớ, sau đó cố gắng để phân bổ một đối tượng mới để ném sẽ không giúp đỡ. –

+3

Bạn có thể ném một con trỏ đến A, hoặc bạn muốn ném std :: bad_alloc, tùy thuộc vào việc A có thể được cấp phát hay không. Vì vậy, ít nhất bạn muốn ném một cái gì đó ... –

+0

Tôi đã nhìn thấy mã như 'const std :: runtime_error err; ném err; 'am tôi đúng giả định rằng điều này sẽ không trong thực tế bị bắt bởi tham chiếu (không có chuyển đổi từ' const std :: runtime_error & 'để' std :: runtime_error & ')? Điều này do đó sẽ bị bắt bởi thời gian chạy và có lẽ là sụp đổ chương trình. Tôi có đúng không? –

1

Không thực sự là một kịch bản tốt để bắt/ném ngoại lệ bằng con trỏ. C + + ngữ nghĩa cho phép nó, nhưng nó không phải là hữu ích khủng khiếp, như hầu hết thời gian bạn sẽ được ném một ngoại lệ tạm thời hoặc đối tượng chuỗi.

Tuy nhiên, một số thư viện (Boost.Graph thực hiện điều này, tôi tin) sử dụng lệnh ném để chuyển giá trị trả lại cho người gọi từ một hàm được đệ quy sâu; trong một tình huống như thế này, giá trị trả lại có thể là một con trỏ, vì vậy việc ném một con trỏ sẽ có ý nghĩa.

14

Bắt theo quy tắc tương thích gán thông thường, nghĩa là, nếu bạn ném một giá trị, bạn có thể xem nó dưới dạng giá trị hoặc tham chiếu, nhưng không phải là con trỏ; nếu bạn ném một con trỏ, bạn có thể bắt nó chỉ như một con trỏ (hoặc tham chiếu đến một con trỏ ...).

Nhưng nó không thực sự có ý nghĩa để ném con trỏ, nó sẽ chỉ gây ra nhức đầu quản lý bộ nhớ. Vì vậy, bạn nên, nói chung thực hiện theo các quy tắc ném theo giá trị, bắt bằng cách tham khảo, như giải thích bởi Gregory.

4

MFC của Microsoft sử dụng bắt bằng con trỏ, nhưng tôi nghĩ đó là khả năng tương thích với trình biên dịch trước khi thử và bắt được triển khai đúng; ban đầu họ sử dụng các macro TRY và CATCH để mô phỏng nó. Mỗi ngoại lệ xuất phát từ CException, trong đó có một phương pháp để xác định xem đối tượng có cần xóa hay không.

Tôi không khuyến nghị rằng đối với bất kỳ thiết kế ngoại lệ hiện đại nào. Bắt theo tham chiếu là con đường để đi.

2

Mặc dù có thể ném về cơ bản bất kỳ đối tượng thuộc loại nào, nhưng có rất ít (nếu có) để đạt được bằng cách thực hiện việc này. Phân bổ động hữu ích chủ yếu khi một đối tượng cần có thời gian tồn tại không phù hợp với phân bổ tự động - tức là bạn muốn tuổi thọ của nó độc lập với phạm vi chương trình thông thường.Tuy nhiên,

Trong trường hợp của một đối tượng ngoại lệ, điều đó thực sự không có ý nghĩa gì nhiều. Một đối tượng ngoại lệ thường chỉ được sử dụng bên trong một trình xử lý ngoại lệ và bạn rõ ràng muốn nó bị hủy khi bạn thoát khỏi trình xử lý (cuối cùng) cho ngoại lệ đó.

Có một thực tế là bạn thường muốn giữ mã xử lý ngoại lệ khá đơn giản. Ví dụ: nếu bạn đang cố gắng báo cáo kho lưu trữ/heap miễn phí bị cạn hoặc hỏng, hãy cố gắng phân bổ đối tượng ngoại lệ của bạn mà kho/lưu trữ miễn phí cạn/hỏng thường sẽ không hoạt động ...

Các vấn đề liên quan