2012-04-27 38 views
5

Tôi đang sử dụng scoped_ptr bên trong các chức năng nhỏ như thế này. để tôi không phải gọi xóa. Đây có phải là quá mức cần thiết cho việc sử dụng này không? Các thành viên trong nhóm của tôi thích con trỏ thô và xóa. Chi phí của việc sử dụng scoped_ptr nếu điều này xảy ra được sử dụng trong một con đường rất quan trọng là gì? Điều này không nên được xếp hàng và chính xác tương đương với việc chỉ sử dụng xóa bình thường trong nhị phân được tối ưu hóa?Có quá mức cần thiết để sử dụng scoped_ptr trong các trường hợp đơn giản không?

void myfunc() 
{ 
    boost::scoped_ptr<myobj> objptr = someFactory::allocate(); 
    callsomeotherfunc(objptr.get()); 
} 

Trả lời

8

Tôi không chắc chắn của các hit hiệu suất, nhưng sử dụng scoped_ptr đây đảm bảo myfunc() là ngoại lệ an toàn: nếu callsomeotherfunc() ném một ngoại lệ bộ nhớ cấp phát động vẫn sẽ được giải phóng. Nếu scoped_ptr không được sử dụng và callsomeotherfunc() có thể ném thì hàm sẽ phải được cấu trúc tương tự như sau:

void myfunc() 
{ 
    myobj* objptr = someFactory::allocate(); 

    try 
    { 
     callsomeotherfunc(objptr); 
     delete objptr; 
    } 
    catch (const some_exception&) 
    { 
     delete objptr; 
     throw; 
    } 
} 

Đây là lỗi dễ bị như tất cả những thay đổi tương lai của hàm sẽ cần phải đảm bảo rằng delete objptr; được gọi trên tất cả các khả năng các điểm thoát.

+1

tôi hy vọng 'đẩy mạnh :: scoped_ptr' để chạy càng nhanh trong trường hợp không đặc biệt và nhanh hơn rất nhiều trong trường hợp ngoại lệ cánh là tốn kém với mô hình ZeroCost hiện đại). –

0

Không, không phải. Lợi ích của việc sử dụng con trỏ thông minh (ví dụ: an toàn ngoại lệ và dọn dẹp tài nguyên tự động) cao hơn rất nhiều so với hiệu suất sử dụng vài byte bộ nhớ bổ sung và vài đồng hồ CPU bổ sung cần thiết cho việc tạo, bảo trì và hủy con trỏ thông minh.

+0

..chấp nhận nếu chức năng đạt đến một điểm khi an toàn ngoại lệ và dọn dẹp tài nguyên tự động hoàn toàn không xảy ra. Tôi đoán rằng thiết lập con trỏ thông minh để null sẽ ngăn chặn việc dọn dẹp? –

+0

@Martin Đó là ý tưởng thú vị nhưng tôi không thể nghĩ ra bất kỳ trường hợp nào khi an toàn ngoại lệ và dọn dẹp tài nguyên tự động là không mong muốn - bạn có thể vui lòng cung cấp một số ví dụ không? –

+0

Chắc chắn, dễ dàng: Đổi tên 'callsomeotherfunc (objptr);' tới 'queueObjectToOutputThread (objptr);'. Bây giờ, dọn dẹp tài nguyên tự động sẽ gây ra AV/segfault tai hại, có thể ở một số nơi trong mô-đun khác, được chạy bởi một luồng khác, không liên quan đến mô-đun được cho là 'an toàn' gây ra sự cố. –

3

Tôi sẽ không sử dụng scoped_ptr cho mục đích đó, mà là unique_ptr trong C++ 11 và auto_ptr trong các trình biên dịch cũ hơn, cả hai đều tương đương với trường hợp sử dụng cụ thể của bạn. Cho dù đó là quá mức cần thiết, không, nó không phải là, nó là lựa chọn duy nhất để cung cấp sự an toàn ngoại lệ (nói bất cứ điều gì trong mã số của myfunc hoặc callsomeotherfunc ném, bạn muốn bộ nhớ được phát hành). Hiệu suất khôn ngoan, ba tùy chọn tương đương với một cuộc gọi delete ở cuối hàm trong trường hợp ngoại lệ không được ném và nhanh hơn là có khối try/catch với số delete để trả lại ngoại lệ trong trường hợp ngoại lệ.

Ngoài ra, có vẻ như bạn đang phân bổ từ một nhà máy, trong một số thiết kế mà nhà máy sẽ có hoạt động deallocate cần được gọi thay vì delete. Nếu trường hợp đó xảy ra, bạn có thể xem xét một con trỏ thông minh khác (shared_ptr từ tiêu chuẩn, sẽ là quá mức cần thiết nếu delete là cách giải phóng bộ nhớ thích hợp; hoặc một số số managed_ptr mà bạn cũng có thể cung cấp deleter)

+0

'auto_ptr' mang lại lợi ích gì cho' scoped_ptr' (ngoài việc là 'std' và một là' tăng')? – KillianDS

+0

@KillianDS: Đối với trường hợp cụ thể này thì không. Nhưng nó là tiêu chuẩn và không mang lại một phụ thuộc bên ngoài thêm, và trong trường hợp này nó là một giải pháp hợp lệ. –

+1

@ DavidRodríguez-dribeas: ngữ nghĩa của 'boost :: scoped_ptr' khá khác so với' std :: unique_ptr'. Một thuộc tính đáng chú ý của 'scoped_ptr' là thêm một ý nghĩa ngữ nghĩa vì lợi ích của người đọc: tài nguyên này sẽ không thoát khỏi phạm vi này. –

0

tôi nghĩ rằng tương đương với scoped_ptr sử dụng sẽ là:

void myfunc() 
{ 
    myobj* objptr = someFactory::allocate(); 
    try 
    { 
     callsomeotherfunc(objptr); 
    } 
    catch (...) 
    { 
     delete objptr; 
     throw; 
    } 
    delete objptr; 
} 

tôi biết phiên bản nào tôi muốn viết ...

+0

nó không phải là tương đương, phiên bản 'scoped_ptr' sẽ không quay trở lại vì ngăn xếp thư giãn. – KillianDS

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