2009-03-10 8 views
9

Tôi có một dự án mà tôi muốn sử dụng nhiều con trỏ thông minh hơn. Nhìn chung, tôi đã thành công trong mục tiêu này. Tuy nhiên, tôi đã đi qua một trong những điều mà tôi không chắc chắn những gì "thực hành tốt nhất" là.trả về một 'con trỏ' được yêu cầu phải được giữ bởi một con trỏ thông minh

Về cơ bản tôi muốn trả về "con trỏ" từ một hàm, nhưng yêu cầu rằng người dùng giữ nó trong con trỏ thông minh. Không chỉ vậy, tôi không muốn ủy thác một con trỏ thông minh cụ thể (được chia sẻ so với scoped).

Vấn đề chủ yếu là dường như không có cách thích hợp để nâng cấp scoped_ptr lên shared_ptr (đó sẽ là giải pháp lý tưởng mà tôi nghĩ). Tôi hiểu tại sao họ không làm điều này, vì nó sẽ cho phép chuyển quyền sở hữu mà có thể dẫn đến một số vấn đề như những người std::auto_ptr có.

Tuy nhiên, việc chuyển quyền sở hữu có vẻ là ý tưởng hay cho trường hợp này. Vì vậy, ý tưởng của tôi là như thế này:

// contrived example of factory pattern 
std::auto_ptr<A> func() { return std::auto_ptr<A>(new A); } 

này hoạt động "ok" vì cả hai scoped_ptrshared_ptr có nhà thầu đó mất quyền sở hữu từ một std::auto_ptr.

Vì vậy, câu hỏi của tôi là, thực hành tốt này? Có giải pháp nào tốt hơn không? Các chỉ thay thế thực sự tôi đã có thể đưa ra là sử dụng một mẫu template như giá trị trả về như thế này:

// similar to above example 
template <template <typename> class P> 
P<A> func() { return P<A>(new A); } 

mà thực sự có thể làm việc tốt ngoại trừ việc tôi nghĩ rằng nó sẽ cần một số công việc để làm cho nó cũng làm việc với số scoped_ptr.

Suy nghĩ?

Trả lời

11

Sử dụng std::auto_ptrcác thực hành tốt, trên thực tế đã được đề xuất such example bởi Bjarne Stroustrup.

Ngữ nghĩa di chuyển của auto_ptr cung cấp cho bạn các công cụ phù hợp để giải quyết vấn đề.

Ví dụ:

auto_ptr<Foo> make_foo() 
{ 
    return auto_ptr<Foo>(new Foo); 
} 

Foo *raw_pointer=make_foo().release(); 
shared_ptr<Foo> shared_pointer=make_foo(); 
auto_ptr<Foo> auto_pointer=make_foo(); 

Nếu bạn quay trở lại shared_ptr bạn không thể dự phòng để con trỏ bình thường, với auto_ptr bạn có thể. Bạn có thể nâng cấp auto_ptr để chia sẻ nhưng không phải hướng khác.

Một điểm quan trọng khác, shared_ptr sử dụng tính toán tham chiếu nguyên tử, chậm hơn nhiều công việc đơn giản nhưng đầy đủ hiệu quả mà auto_ptr thực hiện.

P.S .: scoped_ptr chỉ là phiên bản auto_ptr cho người sáng tạo --- không thể sao chép được và không có chỉ số mặc định. Nó giống như phiên bản "ít gây nhầm lẫn" của auto_ptr, so với shared_ptr nó không thuộc tr1. Nói chung không có nhiều lợi thế của việc sử dụng scoped_ptr qua auto_ptr

+0

shared_ptr trong chuỗi tạo đơn không sử dụng tính toán tham chiếu nguyên tử. –

+0

Bạn nói đúng, nhưng theo mặc định, tăng được xây dựng trong phiên bản nhiều luồng. – Artyom

+2

Lợi thế của việc sử dụng scoped_ptr trên auto_ptr là khi bạn muốn làm cho nó rõ ràng bạn không phải sao chép con trỏ. Bạn chỉ đơn giản là không thể với scoped_ptr. Đó là về truyền đạt ý định của bạn, giống như ví dụ của bạn với auto_ptr và chuyển quyền sở hữu. –

3

Nếu bạn xây dựng một nhà máy đó là ok mà bạn chỉ cần trả lại một con trỏ. Và người dùng của nhà máy của bạn có thể đưa ra quyết định của riêng mình như thế nào và nơi để đặt con trỏ này.
Nếu bạn cần thực thi để sử dụng con trỏ thông minh, bạn phải hạn chế lựa chọn vì bạn không muốn chúng sử dụng "sai".
Vì vậy, hãy tăng :: shared_ptr. Nhưng tốt hơn để typedef nó sau đó để MyClassPtr hoặc MyClass :: ptr.
Tuy nhiên, các nhà máy giống như "mới". Khi tôi muốn tôi đặt kết quả mới bên trong của std :: auto_ptr. Nhưng tôi không muốn bị buộc phải gọi "giải phóng" tất cả các lần khi tôi không muốn con trỏ thông minh.

+0

đúng, nhưng tôi muốn thực thi việc sử dụng con trỏ thông minh nếu có thể. –

+0

Tôi đồng ý, tất cả chúng tôi đều là người lớn ở đây. Trả về một con trỏ khỏa thân và cho phép người dùng của mã quyết định cách nắm bắt tốt nhất giá trị trả về. Tôi tin rằng constructor của shared_ptr từ một auto_ptr sẽ biến mất (auto_ptr sẽ không được dùng nữa). –

+0

khi auto_ptr được depricated trong C++ 0x, unique_ptr sẽ được thay thế nó. Tôi sẽ chuyển sang trả về unique_ptr sau đó. – Aaron

1

Với C++ 11 bạn sẽ có thể sử dụng std::unique_ptr như các loại con trỏ thông minh khác có nhà xây dựng mà phải mất một std::unique_ptr. Nếu bạn duy trì danh sách nội bộ các tài nguyên như vậy thì có thể bạn muốn sử dụng std::shared_ptr.