2013-05-24 9 views
8

Eksperymentuję z aktualizowaniem naszego podzielonego na pamięć bloku pamięci, aby wykorzystać cechy typu C++ 11.Czy globalny nowy operator może zostać nadpisany na podstawie cech typu przydzielonego obiektu?

Obecnie możliwe jest, aby zmusić żadnego podziału dowolnego obiektu w dowolnym miejscu, aby być wysłane do prawidłowego basen nadrzędnymi the global new operator w tradycyjny sposób, np

void* operator new (std::size_t size) 
{ // if-cascade just for simplest possible example 
    if (size <= 64) { return g_BlockPool64.Allocate(); } 
    else if (size <= 256) { return g_BlockPool256.Allocate(); } 
    // etc .. else assume arguendo that we know the following will work properly 
    else return malloc(size); 
} 

w wielu przypadkach możemy dalej, jeśli poprawić wydajność obiekty mogą być wysyłane do różnych pul w zależności od cech typu, takich jak is_trivially_destructible. Czy możliwe jest stworzenie nowego globalnego operatora, który jest świadomy przydzielonego typu, a nie tylko żądanego rozmiaru? Coś równoważne

template<class T> 
void *operator new(size_t size) 
{ 
    if (size < 64) 
    { return std::is_trivially_destructible<T>::value ? 
      g_BlockPool64_A.Allocate() : 
      g_BlockPool64_B.Allocate(); } // etc 
} 

przesłanianie użytkownik Nowy operator w każdej klasie nie będzie tu pracować; naprawdę potrzebujemy tego, aby automatycznie pracować dla każdej alokacji w dowolnym miejscu. Nowe miejsce docelowe również nie działa: wymaganie każdego przydziału wygląda tak, jakby było zbyt niewygodne i ludzie zapomnieli go użyć.

+1

Schludny pomysł. Chociaż w jaki sposób bycie zniszczalnym pomaga menedżerowi pamięci? Menedżer nie dba o konstrukcję ani zniszczenie. – GManNickG

+0

@GManNickG Jeśli wszystkie obiekty ulegające zniszczeniu trywialnie zostaną umieszczone w tej samej puli, możemy zwolnić je masowo, po prostu odrzucając stronę pamięci i nie wywołując w ogóle żadnych destruktorów. Jest to jedno wywołanie systemu operacyjnego zamiast milionów deallocations. Przydatne, gdy wszystkie alokacje dla kawałka poziomu idą do bloku i można po prostu wyrzucić przedmiot za burtę, opuszczając ten obszar. Istnieją już inne mechanizmy, które uniemożliwiają ludziom trzymanie wskaźników w tym bloku po ich życiu. – Crashworks

+0

Nie. Ponadto 'return :: new (size);' to nieskończona rekursja. – aschepler

Odpowiedz

3

Krótka odpowiedź brzmi: nie. Funkcje przydział/dealokacji mają następujące Podpisy:

void* operator new(std::size_t); 
void* operator new[](std::size_t); 
void operator delete(void*); 
void operator delete[](void*); 

Najwięcej odstępstw od tych podpisów spowoduje swojej funkcji nie są w ogóle stosowane. W typowej implementacji zasadniczo zastępujesz domyślne implementacje na poziomie łącznika - tzn. Istniejąca funkcja ma pewną szczególną zmasakrowaną nazwę. Jeśli podasz funkcję o nazwie, która jest identyczna z wynikiem, zostanie ona połączona. Jeśli twoja funkcja nie kojarzy się z tą samą nazwą, nie zostanie połączona.

Szablon, który zasugerowałeś, może zostać użyty w niektórych przypadkach, ale jeśli tak, może to prowadzić do niezdefiniowanego zachowania. W zależności od tego, jak ułożyłeś nagłówki (na przykład), możesz skończyć z kodem mieszającym użycie twojego szablonu z domyślnymi funkcjami, w którym to punkcie o najlepszych, na co możesz liczyć, to że szybko i czysto się zawiesi.

Powiązane problemy