[Trả lời cho câu hỏi this]khởi của shared_ptr <T> từ unique_ptr <T[]>
Tôi đã xử lý một chút với con trỏ thông minh để mảng c-phong cách thời gian gần đây. Cuối cùng, tôi sẽ làm điều được khuyên dùng và sử dụng con trỏ thông minh cho vectơ thay vào đó, nhưng trong thời gian đó, tôi có một chút lời khuyên: không sử dụng đối tượng shared_ptr<T>
để quản lý mảng ban đầu được thực hiện với make_unique<T[]>
vì nó sẽ không gọi delete[]
nhưng thay vì delete
.
này dường như không hợp lý với tôi, và tôi đã kiểm tra cả Coliru và Tiêu chuẩn:
Mã này:
#include <iostream>
#include <memory>
int main()
{
std::cout << "start!\n";
auto customArrayAllocator = [](unsigned int num){
std::cout << "custom array allocator\n";
return new int[num];
};
std::cout << "allocator constructed\n";
auto customArrayDeleter = [](int *ptr){
std::cout << "custom array deleter\n";
delete[] ptr;
};
std::cout << "deleter constructed\n";
std::unique_ptr<int[], decltype(customArrayDeleter)>
myUnique(customArrayAllocator(4), customArrayDeleter);
std::cout << "unique_ptr constructed\n";
std::shared_ptr<int>
myShared = std::move(myUnique);
std::cout << "shared_ptr constructed\n";
}
sản xuất sản lượng này:
start!
allocator constructed
deleter constructed
custom array allocator
unique_ptr constructed
shared_ptr constructed
custom array deleter
Điều này dường như chỉ ra rằng dấu phân cách của unique_ptr<T[]>
được chuyển đến shared_ptr<T>
, như tôi mong đợi.
Từ C++ 14 Chuẩn § 20.8.2.2.1 pg. 571 of doc, 585 of pdf
mẫu shared_ptr (unique_ptr & & r);
Nhận xét: Nhà xây dựng này không được tham gia vào độ phân giải quá tải trừ khi unique_ptr :: pointer chuyển đổi thành T *.
Hiệu ứng: Tương đương với shared_ptr (r.release(), r.get_deleter()) khi D không phải là loại tham chiếu, nếu không shared_ptr (r.release(), ref (r.get_deleter())).
An toàn ngoại lệ: Nếu ngoại lệ được ném, hàm tạo không có hiệu lực.
Nếu tôi đọc đúng, điều đó có nghĩa là đối tượng shared_ptr
tự xây dựng từ cả con trỏ và dấu phân cách unique_ptr
. Hơn nữa, đó là sự hiểu biết của tôi (từ câu trả lời cho câu hỏi gốc) rằng loại ::pointer
của unique_ptr<T[]>
là T*
, nên chuyển đổi thành T*
của shared_ptr<T>::pointer
. Vì vậy, các deleter chỉ nên được sao chép ngay từ đối tượng unique_ptr
, phải không?
Đã thử nghiệm của tôi chỉ làm việc vì nó không thực sự tương đương với chức năng của std::make_shared<T[]>
, hoặc là cú pháp
std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);
một tốt, ngoại lệ an toàn (và sạch hơn) thay thế cho
std::shared_ptr<T> mysharedArray(new T[16], [](T* ptr){delete[] ptr;});
và ilk của nó, khi tôi không thể sử dụng số điện thoại shared array của Boost và muốn tránh bao gồm cả số vector
hoặc tiêu đề array
h mã của tôi?
N.B. mặc dù mảng được đảm bảo được xóa chính xác, có một vấn đề an toàn tiềm năng khi chuyển đổi 'unique_ptr '->' shared_ptr '->' shared_ptr ', xem http://stackoverflow.com/q/32483375/981959 –