2010-06-01 32 views
52

Có một số lớp tương đương cho std :: C++ duy nhất trong các thư viện tăng không? Hành vi tôi đang tìm kiếm là có thể có chức năng nhà máy an toàn ngoại lệ, như vậy ...unique_ptr boost tương đương?

std::unique_ptr<Base> create_base() 
{ 
    return std::unique_ptr<Base>(new Derived); 
} 

void some_other_function() 
{ 
    std::unique_ptr<Base> b = create_base(); 

    // Do some stuff with b that may or may not throw an exception... 

    // Now b is destructed automagically. 
} 

EDIT: Hiện tại, tôi đang sử dụng hack này, có vẻ như tốt nhất tôi có thể nhận được tại thời điểm này ...

Base* create_base() 
{ 
    return new Derived; 
} 

void some_other_function() 
{ 
    boost::scoped_ptr<Base> b = create_base(); 

    // Do some stuff with b that may or may not throw an exception... 

    // Now b is deleted automagically. 
} 
+0

Ngoài ra, hiệu ứng này có thể được tạo ra bằng cách làm cho hàm tạo bản sao có di chuyển ngữ nghĩa, sau đó kiểm tra hủy trước khi giải phóng? –

Trả lời

64

Không thể tạo một cái gì đó như unique_ptr mà không có C++ 0x (nơi nó là một phần của thư viện chuẩn và do đó Boost không cần phải cung cấp).

Cụ thể không có tham chiếu rvalue, là một tính năng trong C++ 0x, việc triển khai mạnh mẽ unique_ptr là không thể, có hoặc không có Boost.

Trong C++ 03, có một vài lựa chọn thay thế có thể, mặc dù mỗi lỗi có lỗ hổng của chúng.

  • boost::shared_ptr có lẽ là sự thay thế đơn giản nhất về mặt capabilites. Bạn có thể sử dụng nó một cách an toàn ở bất cứ nơi nào bạn muốn sử dụng unique_ptr và nó hoạt động. Nó sẽ không hiệu quả, vì tính toán tham chiếu bổ sung. Nhưng nếu bạn đang tìm kiếm một thay thế thả đơn giản mà có thể xử lý tất cả mọi thứ unique_ptr có thể làm, điều này có lẽ là đặt cược tốt nhất của bạn. (Tất nhiên, shared_ptr cũng có thể làm được nhiều hơn nữa, nhưng nó cũng có thể được sử dụng như một sự thay thế thả vào cho unique_ptr.)
  • boost::scoped_ptr tương tự như unique_ptr nhưng không cho phép chuyển quyền sở hữu. Nó hoạt động tuyệt vời miễn là con trỏ thông minh có nghĩa là duy trì quyền sở hữu độc quyền trong suốt cuộc đời của nó.
  • std::auto_ptr hoạt động rất giống với unique_ptr, nhưng có một vài hạn chế, chủ yếu là không thể lưu trữ trong bộ chứa thư viện chuẩn. Nếu bạn chỉ đơn giản là tìm kiếm một con trỏ cho phép chuyển quyền sở hữu, nhưng nó không có nghĩa là được lưu trữ trong các thùng chứa hoặc được sao chép xung quanh, đây có thể là một cược tốt.
+4

+1 cho 'auto_ptr' - vì' unique_ptr' sẽ không biên dịch trong [các vị trí auto_ptr gây ra lỗi] (http://stackoverflow.com/questions/111478/why-is-it-wrong-to-use-stdauto -ptr-với-stl-container), đây chính xác là những gì OP đang tìm kiếm. –

+4

unique_ptr của Howard Hinnant cho C++ 03 hoạt động khá tốt khi xem xét các giá trị r giá trị không tồn tại. –

+0

Điều này không hoàn toàn đúng, như Howard Hinnant đã chứng minh bằng cách sử dụng mô phỏng ngữ nghĩa di chuyển của nó đã được xem xét trên Boost. Tôi hy vọng rằng một người nào đó sẽ thực hiện triển khai của nó và bao gồm nó trên Boost sớm. –

5

Làm thế nào về unique_ptr từ thư viện interprocess?

+0

Có thể trả lại từ một hàm một cách an toàn không? Tôi không thể tìm thấy bất cứ điều gì về điều đó (nhưng có lẽ tôi chỉ mù). Ngoài ra, nó là "quyền" điều để sử dụng, cho rằng nó trong thư viện interprocess thay vì thư viện con trỏ thông minh? –

+0

@ wowus: Không. Điều đó phụ thuộc vào ngữ nghĩa di chuyển mới trong C++ 0x. Điều đó không thể đơn giản được mô phỏng bằng cách tăng cường - tính năng đó phải tồn tại trong trình biên dịch. –

+0

Chỉ cần nhìn, nó cần tham chiếu giá trị r. Vì vậy, không phải những gì tôi đang tìm kiếm. –

10

Bạn có thể muốn thử 'bằng chứng của khái niệm' unique_ptr<> thi Howard Hinnant cho C++ 03 (từ chối trách nhiệm - Tôi có không):

Một trong mình các ví dụ đang trả lại một số unique_ptr<int>:

unique_ptr<int> factory(int i) 
{ 
    return unique_ptr<int>(new int(i)); 
} 
+0

Tôi đã sử dụng điều này trong mã sản xuất, nó hoạt động khá tốt. Vấn đề duy nhất chúng tôi đã gọi là 'boost :: make_shared', cho một' lớp' với tham số 'unique_ptr'. –

4

Tôi đã sử dụng số 012 của Howard Hinnant. Nếu bạn không thực sự giỏi đọc các lỗi lập trình meta siêu tốc từ trình biên dịch, bạn có thể muốn chỉ đạo rõ ràng. Tuy nhiên nó hoạt động giống như một unique_ptr trong 90% các trường hợp.

Nếu không, tôi khuyên bạn nên chuyển các tham số là boost::scoped_ptr& và trao đổi nội bộ để lấy cắp quyền sở hữu. Để nhận giá trị trả về kiểu unique_ptr, hãy sử dụng auto_ptr. Nắm bắt giá trị trả lại auto_ptr trong một shared_ptr hoặc scoped_ptr để tránh sử dụng trực tiếp auto_ptr.

33

Bắt đầu từ Boost 1.57 có triển khai unique_ptr chính thức trong thư viện Boost.Move.

Từ documentation:

(...) một sự thay thế thả-in cho std :: unique_ptr, có thể sử dụng cũng từ 03 C++ biên dịch.

Mã có sẵn trong <boost/move/unique_ptr.hpp> tệp tiêu đề và sống trong không gian tên boost::movelib. Hơn nữa, thư viện Boost.Move cung cấp chức năng nhà máy make_unique() trong <boost/move/make_unique.hpp>, cũng trong không gian tên boost::movelib.

Do đó ví dụ từ câu hỏi có thể được thực hiện theo cách này:

#include <boost/move/unique_ptr.hpp> 

using boost::movelib::unique_ptr; 

unique_ptr<Base> create_base() 
{ 
    return unique_ptr<Base>(new Derived); 
} 

Xem a live example on Wandbox. Lưu ý rằng mã biên dịch tốt với gcc 4.6.4 ở chế độ C++ 98 (!).

Điều thú vị trong boost::movelib::unique_ptr khi áp dụng cho trường hợp của bạn với lớp cơ sở/có nguồn gốc, việc triển khai cung cấp kiểm tra thời gian biên dịch cho khai báo một destructor ảo trong lớp cơ sở. Nếu bạn tình cờ bỏ qua nó the code won't compile (bấm vào nút "Chạy (...)" để xem thông báo lỗi trình biên dịch).

Một vấn đề nhỏ là bao gồm đến từ thư mục boost/move nhưng mã nằm trong không gian tên boost::movelib (sự khác biệt tinh tế nhưng có thể gây khó chịu).

Xem thêm a thread on boost mailing list để biết thêm chi tiết.

Nhờ Ion Gaztañaga cho đoạn mã hoàn toàn độc đáo và hữu ích này.