Avatar billede heltsikkert Nybegynder
02. december 2008 - 21:20 Der er 10 kommentarer og
1 løsning

C++ container der allokerer hukommelse i klumper

Hej Eksperter,

Er der nogen, der ved om der findes en C++ container et sted, der allokerer hukommelse i klumper. Det findes ikke i STL og efter hvad jeg kan se heller ikke i boost.
Det jeg har brug for er noget i stil med en vector, men jeg skal undgå at kopiere alt indhold, når den udvides. En container som f.eks. STL-list dur heller ikke. Der er for meget overhead i at have alle de pointers liggende, som følger med en liste. Jeg har ikke brug for random access, så det behøver containeren ikke at supportere.
Implementering af en sådan container vil indeholde en liste af arrays/vectors forestiller jeg mig.
Jeg kan naturligvis blot implementere containeren selv, men tænkte at der måske allerede var nogen, der havde gjort arbejdet.

På forhånd tak.
Avatar billede arne_v Ekspert
02. december 2008 - 21:25 #1
list<vector<T>> med en tynd wrapper omkring ?
Avatar billede heltsikkert Nybegynder
02. december 2008 - 21:36 #2
Ja, noget i den stil. Med en fast størrelse for de indvendige vectors, forestiller jeg mig.
Sagen er at jeg tilføjer elementer enkeltvis og ved ikke fra starten hvor mange der er. Til sidst skal jeg blot løbe igennem dem alle en enkelt gang.
Avatar billede segmose Nybegynder
02. december 2008 - 23:34 #3
Det skulle findes i STL

vector<T,Allocator<T> >

hvor du så skal skrive din egen allocator eller finde en passende standard at bruge.

se om http://www.cplusplus.com/reference/stl/vector/vector.html giver mening for dig.
Avatar billede arne_v Ekspert
03. december 2008 - 04:10 #4
Simpelt eksempel:

#include <iostream>
#include <vector>

using namespace std;

template<class T, int chunksize>
class VecVec
{
    private:
        vector< vector<T> > data;
        int n;
    public:
        VecVec()
        {
            n = 0;
        }
        void add(T o)
        {
            if(n % chunksize == 0)
            {
                data.push_back(vector<T>());
                data[n / chunksize].reserve(chunksize);
            }
            data[n / chunksize].push_back(o);
            n++;
        }
        T get(int ix)
        {
            return data[ix / chunksize][ix % chunksize];
        }
        int size()
        {
            return n;
        }
};

int main()
{
    VecVec<int,3> vv;
    for(int i = 0; i < 7; i++)
    {
        vv.add(i);
    }
    for(int i = 0; i < vv.size(); i++)
    {
        cout << vv.get(i) << endl;
    }
    return 0;
}
Avatar billede arne_v Ekspert
03. december 2008 - 04:10 #5
API bør nok laves lidt mere STL agtigt, men ideeen må fremgå.
Avatar billede arne_v Ekspert
03. december 2008 - 04:11 #6
segmose>

Vil en allocator ikke bare blive kaldt hver gang vector skal udvides ?
Avatar billede heltsikkert Nybegynder
03. december 2008 - 20:38 #7
@segmose: Jeg mener heller ikke at jeg kan klare det ved at implementere en ny allocator. Den vil stadig af vectoren blive sat til at allokere alt hukommelse på ny, hvis vectoren udvides.

@arne_v: Lige præcis. Klassen VecVec er præcis hvad jeg har brug for, og nu har du jo gjort arbejdet, så jeg kan jo selvfølgelig blot kopiere ovenstående, men jeg tænkte om der ikke fandtes en standard-klasse, der gør det samme. Jeg tror dog at jeg vil bruge en STL-list yderst i data, da man ellers risikerer at alt data skal kopieres, hvis den yderste vector skal udvides. Alternativt kunne man opbevare pointers (til vectors) i den yderste vector. Læg et svar, så uddeler jeg point.

Jeg er stadig interesseret i at høre om der er nogen, der har kendskab til en standard implementering af det arne_v foreslår ovenfor.
Avatar billede arne_v Ekspert
04. december 2008 - 04:22 #8
Jep. list<vector<T>> var jo også hvad jeg startede med.

Her er zweiter verbesserte udgave:

#include <iostream>
#include <list>
#include <vector>

using namespace std;

template<class T, int chunksize>
class ListVec
{
    private:
        list< vector<T> > data;
    public:
        void add(T o)
        {
            if(data.size() == 0 || data.back().size() % chunksize == 0)
            {
                data.push_back(vector<T>());
                data.back().reserve(chunksize);
            }
            data.back().push_back(o);
        }
        T& get(int ix)
        {
            typename list< vector<T> >::iterator it = data.begin();
            for(int i = 0; i < ix/chunksize; i++) it++;
            return (*it)[ix % chunksize];
        }
        T& operator[](int ix)
        {
            return get(ix);
        }
        int size()
        {
            return (data.size() - 1) * chunksize + data.back().size();
        }
};

int main()
{
    ListVec<int,3> vv;
    for(int i = 0; i < 7; i++)
    {
        vv.add(i);
    }
    for(int i = 0; i < vv.size(); i++)
    {
        cout << vv.get(i) << endl;
    }
    vv[2] = 77;;
    for(int i = 0; i < vv.size(); i++)
    {
        cout << vv[i] << endl;
    }
    return 0;
}
Avatar billede arne_v Ekspert
04. december 2008 - 04:22 #9
Og et svar.
Avatar billede segmose Nybegynder
04. december 2008 - 10:02 #10
Ja heltsikkert, det har du nok ret I, Jeg var nok lidt for optimistisk mht. implementeringen, i standarden skulle der være mulighed for forskellige implementation af vector, det er jo ikke et krav at vectors data elementer ligger i rækkefølge fysisk.
Avatar billede heltsikkert Nybegynder
04. december 2008 - 20:23 #11
Jep. Jeg siger tak for hjælpen!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester