Với C ++ 17 , shared_ptr
có thể được sử dụng để quản lý một mảng được phân bổ động. Đối shared_ptr
số mẫu trong trường hợp này phải là T[N]
hoặc T[]
. Vì vậy bạn có thể viết
shared_ptr<int[]> sp(new int[10]);
Từ n4659, [produc.smartptr. Shared.const]
template<class Y> explicit shared_ptr(Y* p);
Yêu cầu: Y
phải là một loại hoàn chỉnh. Biểu thức delete[] p
, khi T
là một kiểu mảng, hoặc delete p
, khi T
không phải là một kiểu mảng, sẽ có hành vi được xác định rõ và không được ném ngoại lệ.
...
Lưu ý: Khi T
là một loại mảng, constructor này sẽ không tham gia vào giải quyết tình trạng quá tải nếu biểu thức delete[] p
là tốt được hình thành và một trong hai T
là U[N]
và Y(*)[N]
là mui trần đến T*
, hoặc T
là
U[]
và Y(*)[]
là chuyển đổi thành T*
. ...
Để hỗ trợ điều này, loại thành viên element_type
hiện được định nghĩa là
using element_type = remove_extent_t<T>;
Các phần tử mảng có thể được truy cập bằng cách sử dụng operator[]
element_type& operator[](ptrdiff_t i) const;
Yêu cầu : get() != 0 && i >= 0
. Nếu T
là U[N]
, i < N
. ... Lưu ý
: Khi T
không phải là kiểu mảng, không xác định được liệu hàm thành viên này có được khai báo hay không. Nếu nó được khai báo, không xác định được kiểu trả về của nó là gì, ngoại trừ việc khai báo (mặc dù không nhất thiết là định nghĩa) của hàm sẽ được định dạng tốt.
Trước khi C ++ 17 , shared_ptr
có thể không được sử dụng để quản lý các mảng cấp phát động. Theo mặc định, shared_ptr
sẽ gọi delete
đối tượng được quản lý khi không còn tham chiếu đến nó. Tuy nhiên, khi bạn phân bổ sử dụng, new[]
bạn cần gọi delete[]
, và không delete
, để giải phóng tài nguyên.
Để sử dụng chính xác shared_ptr
với một mảng, bạn phải cung cấp một deleter tùy chỉnh.
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Tạo shared_ptr như sau:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
Bây giờ shared_ptr
sẽ gọi chính xác delete[]
khi phá hủy đối tượng được quản lý.
Các deleter tùy chỉnh ở trên có thể được thay thế bởi
các std::default_delete
đặc tả từng phần với nhiều loại mảng
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
một biểu hiện lambda
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
Ngoài ra, trừ khi bạn thực sự cần chia sẻ quyền sở hữu của đối tượng được quản lý, unique_ptr
thì phù hợp hơn cho nhiệm vụ này, vì nó có chuyên môn hóa một phần cho các kiểu mảng.
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Những thay đổi được giới thiệu bởi Phần mở rộng C ++ cho Nguyên tắc cơ bản của Thư viện
Một lựa chọn thay thế trước C ++ 17 khác cho các tính năng được liệt kê ở trên được cung cấp bởi Thông số kỹ thuật cơ bản của Thư viện , được tăng cường shared_ptr
để cho phép nó hoạt động tốt trong các trường hợp khi nó sở hữu một mảng các đối tượng. Dự thảo hiện tại về những shared_ptr
thay đổi dự kiến cho TS này có thể được tìm thấy trong N4082 . Những thay đổi này sẽ có thể truy cập thông qua std::experimental
không gian tên và được bao gồm trong <experimental/memory>
tiêu đề. Một vài thay đổi có liên quan để hỗ trợ shared_ptr
cho mảng là:
- Định nghĩa của loại thành viên element_type
thay đổi
typedef T phần tử_type;
typedef typename remove_extent<T>::type element_type;
- Thành viên operator[]
đang được thêm
element_type& operator[](ptrdiff_t i) const noexcept;
- Không giống như unique_ptr
chuyên môn hóa một phần cho mảng, cả hai shared_ptr<T[]>
và shared_ptr<T[N]>
sẽ hợp lệ và cả hai sẽ dẫn đến delete[]
việc được gọi trên mảng đối tượng được quản lý.
template<class Y> explicit shared_ptr(Y* p);
Yêu cầu : Y
phải là một loại hoàn chỉnh. Biểu thức delete[] p
, khi T
là một kiểu mảng, hoặc delete p
, khi T
không phải là một kiểu mảng, sẽ được định dạng tốt, sẽ có hành vi được xác định rõ và không được ném ngoại lệ. Khi T
là U[N]
, Y(*)[N]
phải chuyển đổi thành T*
; khi T
là U[]
, Y(*)[]
phải chuyển đổi thành T*
; nếu không, Y*
sẽ được chuyển đổi thành T*
.
std::vector
. Bạn phải cẩn thận để vượt qua các mảng xung quanh bằng cách sử dụng các tài liệu tham khảo để bạn không tạo ra các bản sao của nó. Cú pháp để truy cập dữ liệu sạch hơn shared_ptr và thay đổi kích thước nó rất dễ dàng. Và bạn nhận được tất cả sự tốt đẹp của STL nếu bạn muốn.