2009-10-21 12 views
8

Chciałbym użyć różnych instancji niestandardowej klasy przydzielania STL do zarządzania różnymi przestrzeniami pamięci, a następnie być w stanie określić instancję alokatora do kontenera STL tak, aby każdy kontener czerpał tylko z przypisana do niego przestrzeń pamięci. Ale nie widzę, jak mogę to zrobić. Widzę, jak mogę przekazać typ alokatora do parametrów szablonu kontenera STL, ale chcę czegoś zbliżonego do przekazania instancji alokatora do konstruktora kontenera STL. Czy istnieje sposób, aby to zrobić w STL?Niestandardowe alokatory STL do zarządzania różnymi przestrzeniami pamięci

Odpowiedz

17

Niestety alokatory STL nie mogą mieć stanu (lub przynajmniej muszą być bardzo ostrożne, w jaki sposób ten stan jest używany) - każda instancja określonego typu alokatora musi być równoważna, aby kontenery STL działały z nimi skutecznie. Nie pamiętam teraz szczegółów, ale wiem, że Scott Meyers długo omawia ten problem pod numerem "Effective STL", pozycja 10: Należy pamiętać o konwencjach i ograniczeniach przydziału.

Jednak może zostały matrycy podzielniki, które są bardzo podobne z różnic między podzielników są obudowane w rodzaju przydzielania i korzystać z różnych „dawałaby” szablonu przydzielania (Każdy szablon „konkretyzacji” jest inny typ) . Ponownie, moje wspomnienie jest takie, że Meyers omawia to dość wyraźnie.

Na przykład zobaczyć ten akapit z artykułu Anthony Aue, "Improving Performance with Custom Pool Allocators for STL":

Potencjalnie poważniejsze zastrzeżenie to, że skoro podzielnik wykorzystuje dane nonstatic, to nie jest technicznie standard zgodny ponieważ wymaga norma że podzielniki tego samego typ jest równoważny. Zobacz Efektywny STL (poz. 10), aby dokładnie wyjaśnić problem. Sprowadza się to do wymagania, aby przydzielający dla danego typu mógł zwolnić pamięć przydzieloną przez dowolne inne wystąpienie alokatora dla tego typu. W przypadku wielu zastosowań standardowych pojemników wymóg ten jest niepotrzebny (niektórzy mogą powiedzieć, że jest to Draconian). Istnieją jednak dwa przypadki, w których to wymaganie jest absolutnie konieczne: list :: splice i swap(). Przypadek zamiany() jest szczególnie poważny, ponieważ jest potrzebny do wdrożenia pewnych operacji na kontenerach w sposób bezpieczny dla wyjątków (patrz Wyjątkowy C++, pozycja 12). Z technicznego punktu widzenia zamiana może być (i w niektórych przypadkach jest) realizowana w obliczu alokatorów, którzy nie porównują jednakowo elementów, które można skopiować lub alokatory można wymieniać razem z danymi - ale nie zawsze tak jest. Z tego powodu, jeśli używasz swap() lub list :: splice, powinieneś upewnić się, że używasz metody HoldingPolicySingleton; w przeciwnym razie możesz popaść w naprawdę paskudne zachowanie.

Zobacz także dyskusję Stephan T. Lavavej w this newsgroup thread.

Będę aktualizować później wieczorem, jeśli ktoś inny nie poda szczegółów w międzyczasie.

+2

Warto jednak zauważyć, że C++ 0x będzie wymagać obsługi nierównych alokatorów. –

+1

Masz rację, na którą warto zwrócić uwagę - FAQ dla Stroustupa na temat C++ 0x "Zakresowe alokatory": http://www.research.att.com/~bs/C++0xFAQ.html#scoped-allocator –

+0

+1 - Chciałbym móc jeszcze bardziej podnieść tę odpowiedź. Alokatory w STL są dość noobowe - przyciągają więcej ezoterycznych błędów niż przyczyniają się do funkcjonalności. – Fox

0

Być może można zakodować zestaw typów alokatorów, który zawiera statyczne wskazanie oddzielnych obszarów pamięci.

Następnie, gdy kontener STL tworzy swój alokator, alokator wykorzystuje przestrzeń pamięci przypisaną do tego przydziału.

Dla uproszczenia załóż, że chcesz użyć dwóch obszarów pamięci. Utwórz dwa typy alokatorów, po jednym dla każdej przestrzeni. Przekaż typ alokatora do konstruktorów kontenerów STL zgodnie z wymaganiami.

6

Kontenery STL umożliwiają przekazywanie alokatora jako argumentu do konstruktora.

Na przykład tutaj są odpowiednie dla konstruktorów wektora:

explicit vector(const Allocator& = Allocator()); 
explicit vector(size_type n, const T& value = T(), 
    const Allocator& = Allocator()); 
template <class InputIterator> 
vector(InputIterator first, InputIterator last, 
    const Allocator& = Allocator()); 

Domyślnie, po prostu użyć domyślnego skonstruowane przydzielania.

Powiązane problemy