C ++ 03
std::auto_ptr
- Có lẽ một trong những bản gốc mà nó mắc phải hội chứng bản thảo đầu tiên chỉ cung cấp các phương tiện thu gom rác hạn chế. Nhược điểm đầu tiên là nó kêu gọi delete
sự phá hủy khiến chúng không được chấp nhận để giữ các đối tượng được cấp phát mảng ( new[]
). Nó có quyền sở hữu con trỏ nên hai con trỏ tự động không được chứa cùng một đối tượng. Việc gán sẽ chuyển quyền sở hữu và đặt lại con trỏ tự động rvalue thành con trỏ null. Điều này có lẽ dẫn đến nhược điểm tồi tệ nhất; chúng không thể được sử dụng trong các vùng chứa STL do không thể sao chép đã nói ở trên. Cú đánh cuối cùng đối với bất kỳ trường hợp sử dụng nào là chúng dự kiến sẽ không được chấp nhận trong tiêu chuẩn tiếp theo của C ++.
std::auto_ptr_ref
- Đây không phải là một con trỏ thông minh mà nó thực sự là một chi tiết thiết kế được sử dụng cùng với std::auto_ptr
để cho phép sao chép và gán trong một số tình huống nhất định. Cụ thể, nó có thể được sử dụng để chuyển đổi một giá trị không phải const std::auto_ptr
thành một giá trị bằng cách sử dụng thủ thuật Colvin-Gibbons còn được gọi là một hàm tạo di chuyển để chuyển quyền sở hữu.
Ngược lại, có lẽ std::auto_ptr
nó không thực sự được sử dụng như một con trỏ thông minh cho mục đích chung để thu gom rác tự động. Hầu hết những hiểu biết hạn chế và các giả định của tôi đều dựa trên Cách sử dụng auto_ptr hiệu quả của Herb Sutter và tôi sử dụng nó thường xuyên mặc dù không phải lúc nào cũng theo cách tối ưu nhất.
C ++ 11
std::unique_ptr
- Đây là người bạn của chúng tôi, người sẽ thay thế std::auto_ptr
nó sẽ khá giống ngoại trừ những cải tiến quan trọng để sửa các điểm yếu std::auto_ptr
như làm việc với mảng, bảo vệ giá trị thông qua phương thức khởi tạo bản sao riêng, có thể sử dụng được với vùng chứa STL và thuật toán, v.v. Vì đó là chi phí hiệu suất và dấu chân bộ nhớ bị hạn chế, đây là một ứng cử viên lý tưởng để thay thế, hoặc có lẽ được mô tả một cách khéo léo hơn là sở hữu con trỏ thô. Vì "duy nhất" ngụ ý chỉ có một chủ sở hữu của con trỏ giống như trước đó std::auto_ptr
.
std::shared_ptr
- Tôi tin rằng điều này dựa trên TR1 và boost::shared_ptr
nhưng được cải thiện để bao gồm răng cưa và số học con trỏ. Tóm lại, nó bao bọc một con trỏ thông minh được tính tham chiếu xung quanh một đối tượng được phân bổ động. Vì "shared" ngụ ý rằng con trỏ có thể được sở hữu bởi nhiều hơn một con trỏ được chia sẻ khi tham chiếu cuối cùng của con trỏ được chia sẻ cuối cùng vượt ra ngoài phạm vi thì đối tượng sẽ bị xóa một cách thích hợp. Đây cũng là các luồng an toàn và có thể xử lý các loại không hoàn chỉnh trong hầu hết các trường hợp. std::make_shared
có thể được sử dụng để xây dựng std::shared_ptr
phân bổ một đống một cách hiệu quả bằng trình cấp phát mặc định.
std::weak_ptr
- Tương tự như vậy dựa trên TR1 và boost::weak_ptr
. Đây là một tham chiếu đến một đối tượng thuộc sở hữu của a std::shared_ptr
và do đó sẽ không ngăn cản việc xóa đối tượng nếu std::shared_ptr
số lượng tham chiếu giảm xuống không. Để có quyền truy cập vào con trỏ thô, trước tiên bạn sẽ cần truy cập std::shared_ptr
bằng cách gọi lock
nó sẽ trả về giá trị trống std::shared_ptr
nếu con trỏ sở hữu đã hết hạn và đã bị phá hủy. Điều này chủ yếu hữu ích để tránh số lượng tham chiếu bị treo vô thời hạn khi sử dụng nhiều con trỏ thông minh.
Tăng cường
boost::shared_ptr
- Có thể là dễ sử dụng nhất trong các tình huống khác nhau (STL, PIMPL, RAII, v.v.), đây là con trỏ thông minh được tính tham chiếu được chia sẻ. Tôi đã nghe một vài lời phàn nàn về hiệu suất và chi phí trong một số tình huống nhưng tôi phải bỏ qua chúng vì tôi không thể nhớ lập luận là gì. Rõ ràng nó đã đủ phổ biến để trở thành một đối tượng C ++ tiêu chuẩn đang chờ xử lý và không có nhược điểm nào so với tiêu chuẩn liên quan đến con trỏ thông minh.
boost::weak_ptr
- Giống như mô tả trước đây std::weak_ptr
, dựa trên việc triển khai này, điều này cho phép một tham chiếu không sở hữu đến a boost::shared_ptr
. Bạn không ngạc nhiên khi gọi lock()
để truy cập con trỏ chia sẻ "mạnh" và phải kiểm tra để đảm bảo rằng nó hợp lệ vì nó có thể đã bị phá hủy. Chỉ cần đảm bảo không lưu trữ con trỏ chia sẻ được trả về và để nó ra khỏi phạm vi ngay sau khi bạn hoàn thành việc đó, nếu không bạn sẽ quay lại ngay vấn đề tham chiếu tuần hoàn nơi số lượng tham chiếu của bạn sẽ bị treo và các đối tượng sẽ không bị phá hủy.
boost::scoped_ptr
- Đây là một lớp con trỏ thông minh đơn giản với ít chi phí có thể được thiết kế để thay thế hoạt động tốt hơn boost::shared_ptr
khi có thể sử dụng. Nó có thể so sánh std::auto_ptr
đặc biệt với thực tế là nó không thể được sử dụng một cách an toàn như một phần tử của vùng chứa STL hoặc với nhiều con trỏ đến cùng một đối tượng.
boost::intrusive_ptr
- Tôi chưa bao giờ sử dụng cái này nhưng theo hiểu biết của tôi, nó được thiết kế để sử dụng khi tạo các lớp tương thích với con trỏ thông minh của riêng bạn. Bạn cần tự thực hiện việc đếm tham chiếu, bạn cũng sẽ cần triển khai một vài phương thức nếu bạn muốn lớp của mình là chung, hơn nữa bạn phải triển khai an toàn luồng của riêng mình. Về mặt tích cực, điều này có thể cung cấp cho bạn cách tùy chỉnh nhất để chọn và chọn chính xác mức độ "thông minh" mà bạn muốn. intrusive_ptr
thường hiệu quả hơn shared_ptr
vì nó cho phép bạn có một phân bổ heap cho mỗi đối tượng. (cảm ơn Arvid)
boost::shared_array
- Đây là một boost::shared_ptr
mảng. Về cơ bản new []
, operator[]
và tất nhiên delete []
là được đưa vào. Điều này có thể được sử dụng trong các thùng chứa STL và theo như tôi biết thì mọi thứ đều boost:shared_ptr
làm được mặc dù bạn không thể sử dụng boost::weak_ptr
với những thứ này. Tuy nhiên, bạn có thể sử dụng một cách khác boost::shared_ptr<std::vector<>>
cho chức năng tương tự và để lấy lại khả năng sử dụng boost::weak_ptr
cho các tài liệu tham khảo.
boost::scoped_array
- Đây là một boost::scoped_ptr
mảng. Như với boost::shared_array
tất cả tính tốt của mảng cần thiết được đưa vào. Cái này không thể sao chép và vì vậy không thể sử dụng trong các vùng chứa STL. Tôi đã tìm thấy hầu hết mọi nơi bạn muốn sử dụng cái này mà bạn có thể chỉ cần sử dụng std::vector
. Tôi chưa bao giờ xác định cái nào thực sự nhanh hơn hoặc ít chi phí hơn nhưng mảng có phạm vi này dường như ít liên quan hơn nhiều so với một vector STL. boost::array
Thay vào đó, khi bạn muốn tiếp tục phân bổ trên ngăn xếp .
Qt
QPointer
- Được giới thiệu trong Qt 4.0, đây là một con trỏ thông minh "yếu" chỉ hoạt động với QObject
và các lớp dẫn xuất, mà trong Qt framework là hầu hết mọi thứ nên đó không thực sự là một hạn chế. Tuy nhiên, có những hạn chế cụ thể là nó không cung cấp con trỏ "mạnh" và mặc dù bạn có thể kiểm tra xem đối tượng bên dưới có hợp lệ hay isNull()
không, bạn có thể thấy đối tượng của mình bị phá hủy ngay sau khi bạn vượt qua kiểm tra đó, đặc biệt là trong môi trường đa luồng. Qt mọi người coi điều này là không được chấp nhận, tôi tin.
QSharedDataPointer
- Đây là một con trỏ thông minh "mạnh" có khả năng so sánh với boost::intrusive_ptr
mặc dù nó có một số tích hợp an toàn luồng nhưng nó yêu cầu bạn bao gồm các phương pháp đếm tham chiếu ( ref
và deref
) mà bạn có thể thực hiện bằng cách phân lớp QSharedData
. Như với phần lớn Qt, các đối tượng được sử dụng tốt nhất thông qua tính kế thừa phong phú và phân lớp mọi thứ dường như là thiết kế dự kiến.
QExplicitlySharedDataPointer
- Rất giống với QSharedDataPointer
ngoại trừ nó không ngầm gọi detach()
. Tôi gọi đây là phiên bản 2.0 QSharedDataPointer
vì sự gia tăng nhẹ kiểm soát chính xác thời điểm tách ra sau khi số lượng tham chiếu giảm xuống 0 không đặc biệt có giá trị đối với một đối tượng hoàn toàn mới.
QSharedPointer
- Đếm tham chiếu nguyên tử, an toàn chuỗi, con trỏ có thể chia sẻ, xóa tùy chỉnh (hỗ trợ mảng), giống như mọi thứ mà một con trỏ thông minh nên có. Đây là những gì tôi chủ yếu sử dụng như một con trỏ thông minh trong Qt và tôi thấy nó có thể so sánh được với boost:shared_ptr
mặc dù có lẽ chi phí cao hơn đáng kể như nhiều đối tượng trong Qt.
QWeakPointer
- Bạn có cảm thấy một mô hình đang quay lại không? Cũng giống như std::weak_ptr
và boost::weak_ptr
điều này được sử dụng cùng với QSharedPointer
khi bạn cần tham chiếu giữa hai con trỏ thông minh, nếu không sẽ khiến các đối tượng của bạn không bao giờ bị xóa.
QScopedPointer
- Tên này trông cũng quen thuộc và trên thực tế nó dựa trên thực tế boost::scoped_ptr
không giống như phiên bản Qt của con trỏ chia sẻ và con trỏ yếu. Nó có chức năng cung cấp con trỏ thông minh cho một chủ sở hữu duy nhất mà không có chi phí QSharedPointer
làm cho nó phù hợp hơn với khả năng tương thích, mã an toàn ngoại lệ và tất cả những thứ bạn có thể sử dụng std::auto_ptr
hoặc boost::scoped_ptr
cho.