2015-11-09 20 views
9

Giả sử lớp sau:C Tiềm năng ++ biên dịch tối ưu hóa có/không có/chức năng noexcept ném

class Example 
{ 
public: 
... 
    Example& operator=(const Example& rhs); 
... 
private: 
    other_type *m_content; 
    size_t m_content_size; 
} 

Example& Example::operator=(const Example& rhs) 
{ 
    if (this != &rhs) 
    { 
     delete m_content; 
     m_content = nullptr; 
     m_content = getCopiedContent(rhs); 
    } 

    return *this; 
} 

Tôi biết rằng đây không phải là cách tốt nhất để thực hiện operator= nhưng đó là về mục đích, bởi vì câu hỏi của tôi là khoảng hai dòng:

m_content = nullptr; 
    m_content = getCopiedContent(rhs); 

thể thể là trình biên dịch sẽ tối ưu hóa ra m_content = nullptr; mặc dù getCopiedContent không được định nghĩa là throw() hoặc noexcept:

other_type* getCopiedContent(const Example& obj); 

Một mặt trình biên dịch có thể giả định rằng nếu ngay sau khi m_content = nullptr; tôi ghi đè lên giá trị của m_content với giá trị trả về của getCopiedContent, nó có thể tối ưu hóa ra toàn bộ m_content = nullptr; biểu thức. Mặt khác, nếu trình biên dịch tối ưu hóa nó và getCopiedContent ném một ngoại lệ, m_content sẽ chứa một giá trị không hợp lệ.

C++ có trạng thái chuẩn bất kỳ điều gì về trường hợp như vậy không?

+2

Tóm tắt câu chuyện dài: Bạn có thể giả sử mã của bạn hoạt động chính xác như nó sẽ không có bất kỳ tối ưu hóa nào. Ngoại lệ duy nhất cho điều này là RVO và UB. –

Trả lời

4

Có thể trình biên dịch sẽ tối ưu hóa ra m_content = nullptr; mặc dù getCopiedContent không được định nghĩa là throw() hoặc noexcept:

Có. Đây là một hoạt động dự phòng mà không có tác dụng phụ. Bất kỳ trình biên dịch tự tôn trọng nào cũng sẽ tối ưu hóa kho lưu trữ thừa. Trong thực tế, bạn sẽ phải làm việc thực sự khó khăn để giữ cho lưu trữ dư thừa từ được tối ưu hóa ra, chẳng hạn như:

  1. làm cho nó std::atomic (nếu đó là nguyên tử, viết bắt buộc phải để chuyển đến các chủ đề khác)
  2. làm cho nó volatile
  3. vòm write với một số loại hàng rào bộ nhớ (ví dụ như khóa một std::mutex) vì những lý do tương tự như (1)

Mặt khác nếu trình biên dịch opt imizes nó ra và getCopiedContent ném một ngoại lệ, m_content sẽ chứa một giá trị không hợp lệ

Quan sát tốt. Trình biên dịch được phép thực hiện việc viết nullptr trong trình xử lý ngoại lệ. tức là nó có thể sắp xếp lại các hướng dẫn để lưu các hoạt động cung cấp tổng kết quả là 'như thể' nó không có.

Chuẩn C++ có quy định bất kỳ điều gì liên quan đến tình huống như vậy không?

Có. Nó có quy tắc 'as-if'. Trong khi lý luận về một luồng, kết quả hiển thị phải là 'as-if', mỗi câu lệnh của bạn được thực thi tuần tự mà không có sự tối ưu hóa với một mô hình bộ nhớ không có đường ống, không được lưu trữ, rất đơn giản. Lưu ý rằng không có máy tính nào được sản xuất trong 20 năm qua thực sự là đơn giản, nhưng kết quả của chương trình phải như thể nó.

Có một ngoại lệ cho việc này - sao chép bản vẽ. Tác dụng phụ của việc bỏ qua các bản sao dự phòng trong một số trường hợp nhất định không cần phải được bảo tồn. Ví dụ, trong khi bỏ qua các bản sao của các đối số là thời gian và trong RVO.

+0

* "Có. Đây là một hoạt động dự phòng không có tác dụng phụ." * Không, OP không giải thích vì sao nó không phải. Nếu 'getCopiedContent' ném người ta có thể quan sát xem nó có được thực hiện hay không, vì vậy nó phải được thực hiện. –

+0

kịch bản đó được đề cập trong phần thứ hai của câu chuyện. –

+0

Vậy tại sao bạn viết "Có" làm từ đầu tiên trong câu trả lời? Điều đó rõ ràng là sai. Ít nhất viết * "Nó có thể được tối ưu hóa để được thực hiện chỉ' getCopiedContent' thực sự không ném. "* Hoặc một cái gì đó như thế này, một phần về làm nó trong xử lý ngoại lệ sẽ là tốt afaics. –

0

Tôi tin điều này được gọi là Dead Store Elimination.

Tôi không biết liệu tối ưu hóa trình biên dịch có được bao gồm trong các tiêu chuẩn ngoại trừ as-if rule hay không.

Đây là mã cho Clang để loại bỏ cửa hàng chết. http://www.llvm.org/docs/doxygen/html/DeadStoreElimination_8cpp_source.html Thao tác này sẽ chỉ chặn khối địa phương.

Có thể có một số công cụ có thể nội tuyến chức năng và thực hiện phân tích dưới dạng khối cục bộ để xem liệu lưu trữ nullptr đó có thể được loại bỏ hay không. Rõ ràng, một cú ném vào chức năng ở đâu đó sẽ làm cho việc phân tích giữ cửa hàng nullptr.

Rõ ràng, trường hợp bạn mô tả vi phạm quy tắc as-if để không tuân thủ tiêu chuẩn.

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