2010-03-10 38 views
5

Xét đoạn mã sau:Tiêu hủy temporaries chuỗi trong trường hợp ngoại lệ ném

std::string my_error_string = "Some error message"; 

// ... 

throw std::runtime_error(std::string("Error: ") + my_error_string); 

Chuỗi truyền cho runtime_error là một tạm thời được trả về bởi chuỗi của operator+. Giả sử ngoại lệ này được xử lý như sau:

catch (const std::runtime_error& e) 
{ 
    std::cout << e.what() << std::endl; 
} 

Khi nào thì trả về tạm thời bằng chuỗi operator+ bị hủy? Liệu các spec ngôn ngữ có bất cứ điều gì để nói về điều này? Ngoài ra, giả sử runtime_error nhận một đối số const char* và được ném như sau:

// Suppose runtime_error has the constructor runtime_error(const char* message) 
throw std::runtime_error((std::string("Error: ") + my_error_string).c_str()); 

Bây giờ khi nào chuỗi tạm thời trả về bởi toán tử + bị hủy? Nó sẽ bị phá hủy trước khi khối catch cố gắng in nó, và đó là lý do tại sao runtime_error chấp nhận một chuỗi std :: và không phải là một const char *?

+1

Nitpick: 'std :: runtime_error (" Lỗi: "+ my_error_string);' là tốt bởi vì 'my_error_string' là loại chuỗi. Bạn không cần phải gọi một cách rõ ràng hàm tạo 'std :: string' trên' "Lỗi:" 'và làm lộn xộn mã của bạn. –

+1

Tôi muốn 'std :: string (" Error: ") .append (my_error_string)' –

Trả lời

5

Là một đối tượng tạm thời (12,2), kết quả của các + sẽ bị phá hủy như là bước cuối cùng trong việc đánh giá các toàn biểu (1,9/9) có chứa nó. Trong trường hợp này, biểu thức đầy đủ là biểu thức ném .

Một ném biểu hiện xây dựng một đối tượng tạm thời (các ngoại lệ đối tượng) (15,1) (std::runtime_error trong trường hợp này). Tất cả các khoảng thời gian trong biểu thức ném sẽ bị hủy sau khi đối tượng ngoại lệ ngoại lệ được tạo. Ngoại lệ được ném chỉ khi đánh giá biểu thức ném đã hoàn thành, vì sự hủy diệt thời gian là một phần của đánh giá này, chúng sẽ bị phá hủy trước khi hủy các biến tự động được xây dựng từ khối thử được nhập (15.2) và trước đó xử lý được nhập vào.

Các hậu điều kiện trên constructor runtime_error 's là what() lợi nhuận cái gì đó strcmp coi tương đương với những gì c_str() trên được thông qua năm trở lại cuộc tranh cãi.Đó là một khả năng lý thuyết mà một khi số std::string được thông qua như một đối số hàm tạo bị phá hủy, có thể trả về một cái gì đó khác, mặc dù nó sẽ là một việc thực hiện có vấn đề và nó vẫn phải là một chuỗi được kết thúc bằng null. không thể trả về một con trỏ đến một số c_str() cũ của một chuỗi đã chết.

8

runtime_error là một lớp chứa chuỗi. Chuỗi đó sẽ được quản lý cho bạn bởi các cơ chế xây dựng và phá hủy C++ bình thường. Nếu nó chứa một char *, thì điều đó sẽ phải được quản lý một cách rõ ràng, nhưng bạn vẫn sẽ không phải làm bất cứ điều gì với tư cách là người dùng của runtime_error.

Mặc dù những gì bạn có thể đọc ở nơi khác trên internet, C++ được thiết kế để luôn làm "điều hợp lý" - bạn thực sự phải cố gắng hết sức để phá vỡ hành vi hợp lý này, mặc dù tất nhiên là không thể làm như vậy .

+0

Để trả lời câu hỏi hủy: tạm thời được tạo sẽ bị hủy ngay sau khi đối tượng 'std :: runtime_error' tồn tại (ví dụ: constructor của nó đã kết thúc thành công). Tất nhiên, đối tượng có một bản sao của nó, vì vậy nó không quan trọng;) –

3

Lưu ý rằng lớp ngoại lệ runtime_error tạo một bản sao của chuỗi được truyền vào hàm tạo. Vì vậy, khi bạn đang gọi .what() trên đối tượng ngoại lệ, bạn sẽ không nhận được cùng một chuỗi ký tự chính xác mà bạn đã nhập.

Vì vậy, để trả lời câu hỏi của bạn, tạm thời bạn đang yêu cầu bị hủy " tại dấu chấm phẩy "của biểu thức có chứa nó (điều này đúng trong cả phiên bản đầu tiên và thứ hai của câu hỏi), nhưng như tôi đã nói, điều này không thú vị, bởi vì một bản sao của nó đã được tạo ra.

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