2013-09-27 42 views
7

Tôi đang nghĩ đến việc thực hiện một lớp đại diện cho sở hữu của một đồng bộ hóa ban, một cái gì đó như thế này:Người dân địa phương có bị phá hủy trước hoặc sau khi đánh giá giá trị trả về của hàm không?

class CCriticalSectionLock 
{ 
public: 
    CCriticalSectionLock(CCriticalSection &cs) : cs(cs) 
    { cs.Enter(); } 
    ~CCriticalSectionLock() 
    { cs.Leave(); } 
private: 
    CCriticalSection &cs; 
}; 

này trông giống như một cách tốt để có thể mất quyền sở hữu trong một chức năng và đảm bảo quyền sở hữu được phát hành ngay cả khi có nhiều điểm thoát hoặc ngoại lệ. Nó không, tuy nhiên, nâng cao một số vấn đề tinh tế về chính xác khi trình biên dịch sẽ có những thứ khác nhau đánh giá. Hãy xem xét việc sử dụng sau đây:

int MyMethod(void) 
{ 
    not_locked(); // do something not under lock 

    CCriticalSectionLock myLock(someCriticalSection); 

    locked(); // do something under lock 

    return ...; // some expression 
} 

AFAIK, C quy tắc cuộc đời ++ sẽ đảm bảo rằng not_locked() sẽ được gọi là trước khóa được thực hiện, và rằng locked() sẽ được gọi trong khi khóa được tổ chức.

Tuy nhiên, những gì tôi không rõ ràng là chính xác khi biểu thức được trả lại sẽ được đánh giá đối với điểm mà tại đó trình phá khóa khóa được gọi là. Có đảm bảo rằng biểu thức sẽ được đánh giá trước trình hủy không? Tôi sẽ nghĩ như vậy nhưng tôi không chắc chắn 100%, và nếu không nó có thể dẫn đến lỗi rất tinh tế, liên tục, khó tìm!

+0

Trùng lặp: [Điều gì đến trước - ngăn xếp thư giãn hoặc sao chép các giá trị trả lại] (http://stackoverflow.com/q/8923018/220636) – nabulke

+0

@nabulke Vì vậy, đó là lý do tại sao tôi không tìm thấy bất cứ điều gì ... tôi đã tìm kiếm sự phá hủy/đánh giá nhưng điều đó đã được ẩn dưới thư giãn/sao chép. – Kevin

Trả lời

5

Nếu không, điều đó sẽ rất có vấn đề.

Thật vậy, hãy xem xét đoạn mã sau:

int function(){ 

    MyClass myObject; 
    //stuff 
    return 5 + myObject.getNumericalValue(); 
} 

với getNumericalValue() một hàm thành viên đơn giản mà trả về một int dựa trên tính toán trên biến thành viên. Nếu biểu thức được đánh giá sau khi sự hủy diệt của myObject, bạn sẽ có hành vi không xác định, và sử dụng người dân địa phương sẽ là không thể trong tuyên bố trở lại (mà không phải là trường hợp).

Trong trường hợp của bạn, khóa sẽ bị hủy sau khi đánh giá báo cáo trả lại.

Để thêm một số tính nghiêm minh đó, tôi xin trích dẫn tiêu chuẩn (§3.7.3/3, tôi nhấn mạnh):

Nếu một biến với thời gian lưu trữ tự động có khởi hoặc một destructor với tác dụng phụ, nó sẽ không bị phá hủy trước khi kết thúc khối của nó, và cũng không nó sẽ bị loại như một tối ưu hóa ngay cả khi nó dường như được sử dụng

sự kết thúc của khối, cho một hàm, là phía sau er báo cáo trả lại.

+0

Điểm tốt về việc có thể sử dụng một địa phương trong sự trở lại; Tôi đã xem xét điều đó quá nhưng tự hỏi nếu bất kỳ tối ưu hóa có thể sắp xếp lại nó trong trường hợp sự trở lại không tham chiếu địa phương. – Kevin

+0

Tôi biết rất ít về các trình biên dịch, nhưng có thể tạo ra các giả định (như "địa phương không được sử dụng trong câu lệnh trả về, tôi có thể phá hủy nó trước câu lệnh) về những gì người dùng đang làm sẽ là trình biên dịch tôi ở xa tránh xa ...Và trong trường hợp này, nó sẽ rõ ràng là một trình biên dịch không tuân thủ. – JBL

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