2016-07-29 7 views
6

Czy istnieje sposób, aby uniemożliwić std::function w gcc dynamiczne przydzielanie pamięci dla większych obiektów funkcji?Zapobieganie std :: funkcja w gcc z alokacji pamięci lub zwiększenie threshhold

bym spodziewać następujący kod do pracy bez dynamicznej alokacji:

#include <functional> 
#include <iostream> 

// replace operator new and delete to log allocations 
void* operator new (std::size_t n) { 
    std::cout << "Allocating " << n << " bytes" << std::endl; 
    return malloc(n); 
} 
void operator delete(void* p) throw() { 
    free(p); 
} 

    class TestPlate 
    { 
    private: 
     int value; 

    public: 
     int getValue(){ return value; } 
     void setValue(int newValue) { value = newValue; } 

     int doStuff(const std::function<int()>& stuff) { return stuff(); } 

    }; 

int main() 
{ 
    TestPlate testor; 
    testor.setValue(15); 
    const std::function<int()>& func = std::bind(&TestPlate::getValue, &testor); 

    std::cout << testor.doStuff(func) << std::endl; 
    testor.setValue(25); 
    std::cout << testor.doStuff(func) << std::endl; 
} 

Jednak przeznacza 24 bajtów. O ile mogę to powiedzieć, to dlatego, że wskaźnik do metody wymaga 16 bajtów, a wskaźnik do instancji klasy kolejne 8 bajtów. Wydaje się, że jest to większa niż pamięć wewnętrzna dostępna dla obiektu funkcji lub B zwykłego błędu.

Zastanawiam się, czy istnieje sposób obejścia tego rodzaju zachowania bez zmiany podpisu std::function lub tworzenia wielu dodatkowych kodu opakowania.

+0

Standard stwierdza, że ​​_Wnioski są zachęcane do unikania użycia dynamicznie przydzielanej pamięci dla małych obiektów wywoływalnych, na przykład, gdy f jest obiektem zawierającym jedynie wskaźnik lub odniesienie do obiektu i funkcję wskaźnika pointer_. Kompilatory starają się jak najlepiej. Jeśli to nie odpowiada twoim potrzebom, dobrze ... – skypjack

+0

clang + libC++ nie przypisuje żadnej pamięci w twoim przykładzie (http://coliru.stacked-crooked.com/a/52505806440111db) – Praetorian

Odpowiedz

6

Niestety GCC ma function ma tylko miejsce na wskaźnik do funkcji składowej przechowywanej wewnętrznie, więc wynik twojego wiązania nie pasuje.

Można użyć wyrażenia lambda zamiast jednak:

std::function<int()> f = [&]{ return testor.getValue(); }; 

wymaga tylko przestrzeń dla typu zamknięcia zawierającej odniesienie do testor (który jest o połowę mniejszy od wskaźnika do członka, a jedna trzecia rozmiar wyniku wiązania), a GCC definiuje to zamknięcie, aby można było je zapisać w postaci std::function.

+0

@ T.C. rzeczywiście robię - i to jest to, co testowałem. Ale nie to, co tutaj napisałem, z jakiegoś powodu. Dzięki. –

0

Przeglądając wyjątkowo obciążający skórę nagłówek functional z biblioteki libstdC++ (domyślna biblioteka GCC w języku C++), odkryłem, że nie jest możliwe uniknięcie alokacji sterty przy obecnej implementacji. Wygląda na to, że ma on specjalnego menedżera i członka inwokacji, który jest przydzielany stertom i jest wymagany, aby klasa działała. Jeśli naprawdę chcesz spojrzeć na źródło, here you go, ale są tam zdecydowanie czarne sztuki i czary.

Występuje pewna funkcjonalność w nagłówku, co oznacza, że ​​zaplanowano przejście w custom allocators, ale obecnie nie wydaje się, aby zostały one zaimplementowane.

W międzyczasie możesz spróbować Boost.function.

+0

To pozwoli uniknąć alokacji sterty jeśli warunek '__stored_locally' jest prawdziwy. Niestety jest to fałsz dla czegoś większego niż wskaźnik funkcji składowej, więc nie może przechowywać tego i wskaźnika do obiektu lokalnie. –

Powiązane problemy