2013-07-29 24 views
5

Trong C++ 11 này bị phản đối:Tại sao "ngoại lệ động" đảm bảo nguyên nhân trên không?

void foo() throw(); 

và thay thế bằng

void foo() noexcept; 

Trong this article nó được giải thích rằng lý do cho điều này (trong số những người khác, đó đun sôi xuống để điều tương tự) là

Thông số kỹ thuật ngoại lệ C++ được kiểm tra trong thời gian chạy chứ không phải lúc biên dịch, vì vậy họ không có lập trình viên đảm bảo rằng tất cả ngoại lệ đã được xử lý.

Trong khi điều này không có ý nghĩa với tôi, tôi không hiểu tại sao throw() được kiểm tra tự động ở nơi đầu tiên, hoặc tại sao noexcept không bảo lãnh ngoại lệ khác ngoài gọi std::terminate thay vì chồng bình thường nghiền (mà không phải là thực sự là một IMO đảm bảo chắc chắn).

Không thể kiểm tra xem có ngoại lệ được ném hay không trong thời gian biên dịch và không biên dịch nếu điều này xảy ra? Như tôi đã nhìn thấy nó, về cơ bản có ba trường hợp:

void foo() noexcept 
{ 
    // 1. Trivial case 
    throw myexcept(); 

    // 2. Try-catch case 
    // Necessary to check whether myexcept is derived 
    // from exception 
    try 
    { 
     throw myexcept(); 
    } 
    catch(exception const & e) 
    {} 

    // 3. Nested function call 
    // Recursion necessary 
    bar(); 
} 

Với các mẫu trong C++ được khởi tạo cho tất cả các loại, biên dịch các ứng dụng sẽ mãi mãi anyways - vậy tại sao không thay đổi noexcept để buộc các trình biên dịch để kiểm tra xem trường hợp ngoại lệ được ném trong thời gian biên dịch?

Khó khăn duy nhất tôi thấy là một hàm có thể hoặc không thể ném tùy thuộc vào trạng thái thời gian chạy - nhưng chức năng đó không được phép tự gọi chính nó là noexcept theo ý kiến ​​của tôi.

Tôi có thiếu thứ gì đó hoặc không có ý định tăng thêm thời gian biên dịch hay để dễ dàng thực hiện các nhà phát triển trình biên dịch?

+13

Không có cách nào để trình biên dịch biết liệu, một hàm thư viện mà bạn gọi bên trong hàm của bạn có ném ngoại lệ hay không. – lapk

+4

'throw()' là một sự bảo đảm mà trình biên dịch tạo ra cho bạn. 'noexcept' là một bảo đảm bạn thực hiện cho trình biên dịch. –

+0

@PetrBudnik: Tất nhiên có, bất kỳ hàm nào không được đánh dấu là 'noexcept' có thể' ném'. –

Trả lời

1

Tôi nghĩ rằng rất nhiều sự kiện đã xảy ra khi các đặc tả ngoại lệ được xác định, các nhà biên dịch cũng đứng sau đường cong điện. Việc triển khai C++ 98 đủ phức tạp đến mức chỉ có một trình biên dịch mà ngay cả đã yêu cầu để triển khai tất cả các tính năng của nó. Mọi trình biên dịch khác đều bỏ sót ít nhất một tính năng chính được đưa vào tiêu chuẩn. Hầu hết công khai thừa nhận rằng họ đã rời xa đáng kể hơn thế.

Bạn cũng cần lưu ý rằng các đặc điểm ngoại lệ động cũng phức tạp hơn đáng kể so với chỉ throw(). Nó cho phép một lập trình viên chỉ định một tập các kiểu tùy ý có thể được ném ra. Tệ hơn nữa, xác định rằng một hàm có thể ném foo có nghĩa là nó cũng có thể ném bất cứ thứ gì có nguồn gốc từ foo.

Thực thi các đặc tả ngoại lệ tĩnh có thể đã được thực hiện, nhưng rõ ràng là đã thêm khá nhiều công việc phụ, và không ai thực sự chắc chắn lợi ích (nếu có) nó sẽ cung cấp. Trong hoàn cảnh, tôi nghĩ rằng nó là khá dễ dàng cho hầu hết các suy nghĩ rằng thực thi tĩnh là một cái gì đó mà có thể được yêu cầu sau này nếu có vẻ là đủ sử dụng để biện minh cho công việc. Thay đổi từ việc thực thi tại thời gian chạy đến thời gian biên dịch sẽ không yêu cầu sửa đổi mã hiện có, chỉ các triển khai hiện có.

Một điểm khác là tôi không chắc chắn có bao giờ thực sự mạnh mẽ hỗ trợ các đặc điểm ngoại lệ hay không. Tôi nghĩ rằng có một thỏa thuận chung về ý tưởng cơ bản, nhưng khi bạn nhận được nó, có lẽ ít hơn về các chi tiết.

Tóm lại: dễ dàng chỉ định thực thi động và để thực thi tĩnh cho sau này (nếu có). Hóa ra, thực thi tĩnh có lẽ sẽ không thực sự thêm tất cả những gì tích cực trong mọi trường hợp, do đó, bắt buộc nó có lẽ sẽ không hoàn thành nhiều anyway.