2012-04-05 32 views
7

Tôi có một vấn đề với auto_ptr trong các lớp ngoại lệ, mà tôi thậm chí giảm xuống còn:Tại sao tôi không thể có một auto_ptr trong một lớp ngoại lệ

#include <memory> 

class MyException 
{ 
    std::auto_ptr<int> m_foo2; 
}; 

int main() 
{ 
    try 
    { 
     throw MyException(); 
    } 
    catch (const MyException&) 
    { 

    } 
    return 0; 
} 

này thất bại trong việc biên dịch với:

/perforce/unstable/test/Common/Exceptions/TestException4.cpp: In function 'int main()': /perforce/unstable/test/Common/Exceptions/TestException4.cpp:12: error: no matching function for call to 'MyException::MyException(MyException)' /perforce/unstable/test/Common/Exceptions/TestException4.cpp:4: note: candidates are: MyException::MyException() /perforce/unstable/test/Common/Exceptions/TestException4.cpp:4: note: MyException::MyException(MyException&) /perforce/unstable/test/Common/Exceptions/TestException4.cpp:12: error: in thrown expression

Và lỗi sẽ biến mất nếu tôi xóa auto_ptr.

Đây có phải là do ngoại lệ được sao chép hoặc gán không? Có cách nào để sử dụng auto_ptr s trong Ngoại lệ không?

+0

Câu trả lời chất lượng cao, tuyệt vời tại đây. Phải là một câu hỏi hay. :) – sje397

Trả lời

9

Is this because the exception is being copied or assigned?

Thực tế là vậy. Tiêu chuẩn chỉ định cách ngoại lệ được ném vào C++ 11 15.1/3:

A throw-expression initializes a temporary object, [...]. The temporary is an lvalue and is used to initialize the variable named in the matching handler.

Việc khởi tạo được thực hiện với hàm tạo bản sao ẩn. Điều này được khai báo là MyException(MyException&), vì có một thành viên yêu cầu đối số tham chiếu không phải là const (như được chỉ rõ trong C++ 11 12.8/9). Đối tượng tạm thời không thể bị ràng buộc với tham chiếu không phải là const và do đó việc xây dựng không thành công.

Is there a way of using auto_ptrs in an Exception?

Nếu bạn có thể sử dụng C++ 11, sau đó bạn có thể sử dụng unique_ptr thay vào đó, và ký gửi auto_ptr để ruột của lịch sử. Lớp của bạn sẽ có một hàm tạo di chuyển ngầm, được khai báo là MyException(MyException&&), có thể được sử dụng để khởi tạo nó từ tạm thời.

Nếu không, bạn có thể ném một giá trị không phải là tạm thời:

MyException ex; 
throw ex; 

hoặc bạn có thể hack lớp học của bạn để cho phép khởi động từ một tài liệu tham khảo const bằng cách thêm một constructor sao chép rõ ràng và sử dụng const_cast hoặc mutable để cho phép điều đó để sao chép các auto_ptr - nhưng đó là nguy hiểm tiềm tàng, và tôi sẽ không khuyên bạn nên nó.

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