2015-02-09 22 views
8

Próbuję użyć std::unique_ptr<T[]> z niestandardowych podzielników pamięci. Zasadniczo mam niestandardowych podzielniki, które są podklasy IAllocator, który przewiduje następujące metody:std :: unique_ptr <T[]> i niestandardowy delikator przydzielania

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) 

Ponieważ pamięć bazowy może pochodzić z wstępnie przyznane bloku, muszę specjalnych ...Array() -methods do alokacji i bezpłatne tablice , przydzielają/zwalniają pamięć i wywołują T()/~T() na każdym elemencie w zakresie. Teraz, o ile mi wiadomo, niestandardowe deleters dla std::unique_ptr użyć Podpis:

void operator()(T* ptr) const 

W przypadku unique_ptr<T[]>, normalnie można nazwać delete[] i być z nim zrobić, ale mam zadzwonić FreeArray<T>, dla których Potrzebuję liczby elementów w zakresie. Biorąc pod uwagę tylko surowego wskaźnik, myślę, że nie ma możliwości uzyskania wielkości zakresie, stąd jedyne co mogłam wymyślić to:

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

Gdzie zasadniczo rozmiar tablicy musi być przekazywana do obiektu deletera ręcznie. Czy jest lepszy sposób to zrobić? Wydaje mi się to bardzo podatne na błędy ...

Odpowiedz

7

Tak, tam na pewno jest lepszy sposób:
Użyj maker-funkcyjnego.

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* nie zawiera takich informacji, ani unique_ptr nie wie o rozmiarze tablicy (ponieważ używa ona bezpośrednio podanego delete []). Możesz pozwolić T być unique_ptr<T>, aby automatycznie zarządzać zniszczeniem, ale nie będzie to możliwe, jeśli cały ciągły obiekt T* jest zarządzany przez alokację pamięci (a nie pojedynczy obiekt T*). Np:

unique_ptr<unique_ptr<Foo>[]> data; 
data.reset(new unique_ptr<Foo>[50]); 
data[0].reset(new Foo());