2015-02-09 20 views
8

Tôi đang cố gắng sử dụng std::unique_ptr<T[]> với bộ cấp phát bộ nhớ tùy chỉnh. Về cơ bản, tôi có allocators tùy chỉnh mà là lớp con của IAllocator, cung cấp các phương pháp sau:std :: unique_ptr <T[]> và deleter phân bổ tùy chỉnh

void* Alloc(size_t size) 
template<typename T> T* AllocArray(size_t count) 
void Free(void* mem) 
template<typename T> void FreeArray(T* arr, size_t count) 

Kể từ khi bộ nhớ tiềm ẩn có thể đến từ một khối tiền phân bổ, tôi cần những ...Array() -methods đặc biệt để phân bổ và mảng miễn phí , họ phân bổ/giải phóng bộ nhớ và gọi T()/~T() trên mọi phần tử trong phạm vi. Bây giờ, theo như tôi biết, deleters tùy chỉnh cho std::unique_ptr sử dụng chữ ký:

void operator()(T* ptr) const 

Trong trường hợp của unique_ptr<T[]>, thông thường bạn sẽ gọi delete[] và được thực hiện với nó, nhưng tôi phải gọi FreeArray<T>, mà Tôi cần số lượng yếu tố trong phạm vi. Đưa ra chỉ con trỏ thô, tôi nghĩ rằng không có cách nào có được kích thước của dãy núi này, do đó điều duy nhất tôi có thể đưa ra là thế này:

std::unique_ptr<T[], MyArrDeleter> somePtr(allocator.AllocArray<T>(20), MyArrDeleter(allocator, 20)); 

yếu Trong trường hợp kích thước của mảng phải được thông qua vào đối tượng deleter theo cách thủ công. Có cách nào tốt hơn để làm điều này? Điều này có vẻ khá dễ bị lỗi ...

Trả lời

7

Có, có chắc chắn nhất là một cách tốt hơn:
Sử dụng một nhà sản xuất chức năng.

template<class T, class A> std::unique_ptr<T[], MyArrDeleter> 
my_maker(size_t count, A&& allocator) { 
    return {somePtr(allocator.AllocArray<T>(count), MyArrDeleter(allocator, count)}; 
} 

auto p = my_maker<T>(42, allocator); 
0

T* không chứa thông tin như vậy, không unique_ptr biết về kích thước của mảng (vì nó sử dụng trực tiếp delete [] như bạn đã nêu). Bạn có thể để Tunique_ptr<T> để tự động quản lý việc hủy diệt nhưng không thể thực hiện được nếu toàn bộ số liên tiếp T* được quản lý bởi bộ cấp phát bộ nhớ (và không phải đối tượng T* đơn lẻ). Ví dụ:

unique_ptr<unique_ptr<Foo>[]> data; 
data.reset(new unique_ptr<Foo>[50]); 
data[0].reset(new Foo()); 
Các vấn đề liên quan