Szukam dla C ++ STL-jak klasa Vector lecz stosując przechowywanie stosu

głosy
44

Przed piszę moja własna zadam wszystko y'all.

Szukam dla klasy C ++, który jest niemal dokładnie jak wektora STL ale zapisuje dane w tablicy na stosie. Jakiś STL klasy przydzielania będzie działać również, ale staram się unikać wszelkiego rodzaju, nawet sterty przydzielone statyczne stosy per-thread (choć jeden z nich jest mój drugi wybór). Stos jest po prostu bardziej wydajny.

To musi być niemal spadek zamiennik dla aktualnego kodu, który wykorzystuje wektor.

Za to, co miałem napisać sam myślałem o czymś takim:

char buffer[4096];
stack_vector<match_item> matches(buffer, sizeof(buffer));

Lub klasa może mieć miejsca w buforze przydzielane wewnętrznie. Wtedy to będzie wyglądać:

stack_vector<match_item, 256> matches;

Myślałam, że to rzucić std :: bad_alloc jeśli zabraknie miejsca, mimo że nigdy nie powinno się zdarzyć.

Aktualizacja

Korzystanie stack_container.h chromu za działa świetnie!

Powodem, dla którego nie myślał robić to w ten sposób, że ja mam zawsze pomijany parametr obiektu podzielnik do konstruktorów zbiórki STL. Użyłem parametr szablonu kilka razy, aby zrobić pul statycznych, ale nigdy nie widziałem kodu lub napisałeś że rzeczywiście używany parametr obiektu. Nauczyłem się czegoś nowego. Bardzo fajny!

Kod jest nieco niechlujny iz jakiegoś powodu GCC zmusił mnie do deklarowania podzielnika jako rzeczywistego elementu zamiast konstruowania go do parametru przydzielania nosiciela. Trwało to z czymś takim:

typedef std::pair< const char *, const char * > comp_list_item;
typedef std::vector< comp_list_item > comp_list_type;

comp_list_type match_list;
match_list.reserve(32);

Do tego:

static const size_t comp_list_alloc_size = 128;
typedef std::pair< const char *, const char * > comp_list_item;
typedef StackAllocator< comp_list_item, comp_list_alloc_size > comp_list_alloc_type;
typedef std::vector< comp_list_item, comp_list_alloc_type > comp_list_type;

comp_list_alloc_type::Source match_list_buffer;
comp_list_alloc_type match_list_alloc( &match_list_buffer );
comp_list_type match_list( match_list_alloc );
match_list.reserve( comp_list_alloc_size );

I muszę powtórzyć, że ilekroć Oświadczam nowy. Ale to działa tak jak chciałem.

Zauważyłem, że stack_container.h ma StackVector zdefiniowany i próbowałem go używać. Ale to nie dziedziczy z wektorem lub określić te same metody, więc nie było zastąpienie drop-in. Nie chciałem przepisać cały kod przy użyciu wektora więc dałem się na niego.

Utwórz 09/12/2008 o 23:15
źródło użytkownik
W innych językach...                            


10 odpowiedzi

głosy
38

Nie trzeba pisać zupełnie nową klasę kontenera. Można trzymać z kontenerów STL, ale zmienić drugi parametr na przykład std::vector, aby nadać mu swój własny przydzielania który przydziela ze stosu bufora. Autorzy chromu napisał przydzielania właśnie do tego:

https://chromium.googlesource.com/chromium/chromium/+/master/base/stack_container.h

Działa poprzez przydzielenie bufor gdzie mówisz, jak duży jest. Utworzyć kontener i zadzwoń container.reserve(buffer_size);. Jeśli przepełnienie, że wielkość, podzielnik automatycznie uzyskać elementy z hałdy (ponieważ pochodzi od std::allocator, będzie w takim przypadku po prostu korzystać z udogodnień w standardzie podzielnika). Nie próbowałem, ale wygląda na to, że to z google więc myślę, że warto spróbować.

Wykorzystanie jest tak:

StackVector<int, 128> s;
s->push_back(42); // overloaded operator->
s->push_back(43);

// to get the real std::vector. 
StackVector<int, 128>::ContainerType & v = s.container();
std::cout << v[0] << " " << v[1] << std::endl;
Odpowiedział 09/12/2008 o 23:27
źródło użytkownik

głosy
15

Wydaje się, że boost :: static_vector to, czego szukasz. Z dokumentacji:

static_vector jest hybrydą pomiędzy wektorem i tablicy: Jak wektorem, to jest pojemnika z sekwencji przyległej pamięci, które mogą zmieniać rozmiar, a także statyczne przydzielanie, niskim narzutem i stałej mocy tablicy. static_vector opiera się na Adama Wulkiewicz i wysokiej wydajności klasy VArray Andrew HUNDT użytkownika.

Liczba elementów w static_vector może zmieniać się dynamicznie do stałej pojemności, ponieważ elementy są przechowywane w samym obiekcie podobny do tablicy.

Odpowiedział 16/01/2014 o 14:23
źródło użytkownik

głosy
11

Niektóre opcje można zajrzeć do:

STLSoft Matthew Wilson (autor Imperfect C ++) ma auto_bufferklasę szablonu, który stawia domyślną tablicę na stosie, ale jeśli rośnie większy niż alokacji stosu przechwyci pamięci ze sterty. Lubię tę klasę - jeśli wiesz, że rozmiary kontenerów są ogólnie będzie ograniczona przez raczej niskim limitem, a następnie pojawi się prędkość lokalna, stos przydzielonej tablicy. Jednak w przypadkach rogu, gdzie trzeba więcej pamięci, to wszystko nadal działa poprawnie.

http://www.stlsoft.org/doc-1.9/classstlsoft_1_1auto__buffer.html

Należy zauważyć, że realizacja używam sobie nie jest STLSoft, ale implementacja że pożycza mocno od niego.

„The Lazy Programmer” zrobiła post dla implementacji kontenera, który wykorzystuje alloca()do przechowywania. Nie jestem fanem tej techniki, ale dam ci sam zdecydować, czy to, co chcesz:

http://tlzprgmr.wordpress.com/2008/04/02/c-how-to-create-variable-length-arrays-on-the-stack/

Wtedy tam boost::arrayktóry nie posiada żadnego z dynamicznego zachowania wymiarowanie dwóch pierwszych, ale daje więcej z vectorinterfejsem niż tylko za pomocą wskazówki jak iteratory które można uzyskać z wbudowanymi tablicami (tj dostać. begin(), end(), size(), Itd.):

http://www.boost.org/doc/libs/1_37_0/doc/html/boost/array.html

Odpowiedział 10/12/2008 o 02:18
źródło użytkownik

głosy
4

Jeśli prędkość liczy, widzę uruchomić razy

  • 4 d int [10], rozmiar ustalony na stosie
  • 40 ns <vector>
  • 1300 NS <stlsoft/containers/pod_vector.hpp>

dla jednego głupiego testu poniżej - tylko 2 Push, v [0] v [1], 2 pop, na jednej platformie, Mac PPC, gcc-4.2 -O3 tylko. (Nie mam pojęcia, czy ich firmy Apple zostały zoptymalizowane STL).

Nie przyjmujemy żadnych czasy nie zostały sfałszowane siebie. I oczywiście każdy wzór użycie jest inna. Niemniej Czynniki> 2 dziwi mnie.

(Jeśli MEMS, pamięć dostęp, są dominującym czynnikiem w czasy pracy, jakie są wszystkie dodatkowe MEMS w różnych implementacjach?)

#include <stlsoft/containers/pod_vector.hpp>
#include <stdio.h>
using namespace std;

int main( int argc, char* argv[] )
{
        // times for 2 push, v[0] v[1], 2 pop, mac g4 ppc gcc-4.2 -O3 --
    // Vecint10 v;  // stack int[10]: 4 ns
    vector<int> v;  // 40 ns
    // stlsoft::pod_vector<int> v;  // 1300 ns
    // stlsoft::pod_vector<int, std::allocator<int>, 64> v;

    int n = (argv[1] ? atoi( argv[1] ) : 10) * 1000000;
    int sum = 0;

    while( --n >= 0 ){
        v.push_back( n );
        v.push_back( n );
        sum += v[0] + v[1];
        v.pop_back();
        v.pop_back();
    }
    printf( "sum: %d\n", sum );

}
Odpowiedział 29/07/2009 o 12:20
źródło użytkownik

głosy
4

Można użyć własnego przydzielania dla std :: vector i mieć go przeznaczyć fragmenty swojej pamięci na stosie, podobnych do przykładu. Klasa podzielnik jest drugą częścią szablonu.

Edit: Nigdy nie próbowałem tego, a patrząc na dalszą dokumentację prowadzi mnie do przekonania, że ​​nie można napisać własny przydzielania. Jestem wciąż patrząc na niego.

Odpowiedział 09/12/2008 o 23:18
źródło użytkownik

głosy
3

TR1 :: array częściowo pasuje do opisu. Brakuje rzeczy jak naciśnięciem ___ back (), itd., ale to może być warte przyjrzeniu się jako punkt wyjścia. Owijając go i dodanie indeksu do „wstecz” w celu wspierania push_back (), itd. Powinny być dość łatwe.

Odpowiedział 09/12/2008 o 23:39
źródło użytkownik

głosy
2

To może być tak, że używasz Qt. To może chcesz iść do QVarLengthArray( docs ). To siedzi w zasadzie między std::vectori std::array, przeznaczając statycznie dla pewnej wysokości i spada z powrotem do alokacji sterty w razie potrzeby.

Wolałbym wersję doładowania jeśli używałem go jednak.

Odpowiedział 13/05/2014 o 21:00
źródło użytkownik

głosy
2

Dlaczego chcesz, aby umieścić go na stosie w szczególności? Jeśli masz implementację alloca (), można Buld do przydzielania klasy przy użyciu że zamiast malloc (), ale twój pomysł wykorzystania statycznie przydzielonego tablicy jest jeszcze lepiej: to tak szybko na większości architektur, a ty nie ryzyko stos korupcja bałagan.

Odpowiedział 09/12/2008 o 23:25
źródło użytkownik

głosy
1

Zwiększ mieć ten. Nazywa small_vector

small_vector jest pojemnik wektor jak optymalizowane dla przypadku, gdy zawiera on kilka elementów. Zawiera on kilka zdefiniowanej przez elementy w miejscu, co pozwala to na uniknięcie stosowania dynamicznej alokacji pamięci, gdy rzeczywista liczba elementów jest poniżej tej zdefiniowanej przez próg. small_vector jest inspirowana przez SmallVector pojemnika na LLVM. W przeciwieństwie static_vector, pojemność small_vector może rosnąć poza początkowej pojemności zdefiniowanej przez.

small_vector jest zamienny do small_vector_base, typ, który jest niezależny od zdefiniowanej przez liczby elementów, dzięki czemu kod klienta, który nie musi być na tej matrycy N argument. small_vector dziedziczy wszystkie funkcje składowe wektorze tak, że obsługuje wszystkie standardowe funkcje, takie jak umiejscowienie, stanowych podzielników itd

Odpowiedział 21/04/2016 o 08:50
źródło użytkownik

głosy
0

Jeśli chcesz przeznaczyć na stosie, ale nie chce, aby wstępnie określić maksymalną wielkość w czasie kompilacji, można użyć StackVector , małą realizację które mogą być używane w ten sposób:

new_stack_vector(Type, name, size)

gdzie Typejest typ elementu w wektorze namejest zmienna nazwa wektora, i sizejest to maksymalna liczba elementów, które pozwalają w wektorze.

sizemoże być zmienna i nie musi być stałą czasu kompilacji! :RE

Przykład:

new_stack_vector(int, vec, 100); //like vector<int> vec; vec.reserve(100); but on the stack :)
vec.push_back(10); //added "10" as the first item in the vector

...i to wszystko!

Uwaga: Nigdy nie należy używać bardzo duże rozmiary tablic na stosie w ogóle. Jak nie powinno się używać int var[9999999], nie należy używać podobnie new_stack_vector(int, vec, 9999999)! Używać odpowiedzialnie.

Odpowiedział 07/03/2018 o 13:27
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more