Array oder std::vector?



  • Hallo

    Ich muss ehrlich sagen, dass ich immer std::vector verwende, weil ich damit einfach besser klarkomme und noch keinen Nachteil kenne. (Ich lasse mich aber gerne aufklären.)

    chrische



  • Rohes Array braucht man nie, denn es gibt ja noch boost::array 😉



  • Naja, nicht nur in Boost. Im TR1 gibts sogar std::tr1::array. Nie wieder rohe Arrays! 😃 Aber als Übergang kann man natürlich boost::array benutzen.



  • chrische5 schrieb:

    Ich muss ehrlich sagen, dass ich immer std::vector verwende, weil ich damit einfach besser klarkomme und noch keinen Nachteil kenne. (Ich lasse mich aber gerne aufklären.)

    Kommt sicherlich auf die Implementierung an und auch was man mit dem Container "aussagen" will. Denn Code soll ja auch sprechend sein.

    std::vector von Dinkumware reserviert am Anfang nur soviel wie auch drin ist. Packt man also ein Element rein, verbraucht Dinkumwares vector auch nur Platz für ein Array-Element. Macht also ggü. z.B. boost::array keinen Nachteil. Andere Implementierungen könnten z.B. 64 Elemente vorreservieren, selbst wenn nichts drin ist. Kann sich auf Systemen mit wenig Speicher schon summieren.

    Ein Array hat aber eine feste Größe. boost::array ist z.B. in der Größe nicht änderbar, hat aber ansonst den Komfort eines Vectors. Wenn man weiß, das man kein dynamisches Array benötigt, muß man trotzdem kein C-Array nehmen. Benutzt einfach brav Boost oder bald tr1.

    Achja, beim boost::array und std::tr1::array kann man sowas machen:

    array<int, 3> a = {1,2,3};
    

    Ist doch auch was, oder? 🙂



  • boost ist aber nicht im standard enthalten, oder?

    Würdet ihr für Bilddaten auch den std::vector nehmen?



  • Artchi schrieb:

    array<int, 3> a = {1,2,3};
    

    Sorry, wenns nicht hierher gehört, aber wie ist das denn implementiert. Sprich welche Operatoren muss man für sowas überladen?



  • bluecode schrieb:

    Artchi schrieb:

    array<int, 3> a = {1,2,3};
    

    Sorry, wenns nicht hierher gehört, aber wie ist das denn implementiert. Sprich welche Operatoren muss man für sowas überladen?

    Schau's dir an. Steht in den Headerdateien.

    Würdet ihr für Bilddaten auch den std::vector nehmen?

    ja

    mfg.



  • bluecode schrieb:

    Sorry, wenns nicht hierher gehört, aber wie ist das denn implementiert. Sprich welche Operatoren muss man für sowas überladen?

    keine 🙂 Das ist ein alter Trick

    struct B
    {
    	int a, b, c;
    };
    
    struct X
    {
    	B b1;
    	int i;
    	B b2[2];
    };
    
    int main()
    {
    
    	B b = 
    	{
    		1,						//a
    		2,						//b
    		3						//c
    	};
    
    	X x = 
    	{
    		{1, 2, 3},				//b1
    		4,						//i
    		{{5, 6, 7}, {8, 9, 10}}	//b2
    	};
    
    	x;
    
    }
    

  • Mod

    das geht, weil boost::array ein aggregat ist. dafür muss es auf einen selbstdefinierten konstruktor und destruktor verzichten, was dazu führt, dass boost::array nur fast ein container im sinne der standard bibliothek ist.



  • Übertreibe ich jetzt oder bin ich rückständig?

    Wieso zum Teufel nehmt ihr für Arrays std::vector oder boost::array. Bald kommt bestimmt boost::bool.

    Ich finde normale Arrays da einfach praktischer.



  • _42 schrieb:

    Wieso zum Teufel nehmt ihr für Arrays std::vector oder boost::array. Bald kommt bestimmt boost::bool.

    Haha, sehr gut 😃

    Nimm für Bilddaten bitte normale arrays!! Da kannst du dann auch einfach mit read binary Daten reinlesen!

    m_image = new char[dim_x*dim_y];
    	FileBin.read(m_image , FileSize);
    	FileBin.close();
    

    Grüße vom boost:void*



  • Bald kommt bestimmt boost::bool.

    Wieso kommt noch? Gibts doch schon! 😃

    http://www.boost.org/doc/html/tribool.html

    :p



  • Gast25250 schrieb:

    _42 schrieb:

    Wieso zum Teufel nehmt ihr für Arrays std::vector oder boost::array. Bald kommt bestimmt boost::bool.

    Haha, sehr gut 😃

    Nimm für Bilddaten bitte normale arrays!! Da kannst du dann auch einfach mit read binary Daten reinlesen!

    m_image = new char[dim_x*dim_y];
    	FileBin.read(m_image , FileSize);
    	FileBin.close();
    

    Grüße vom boost:void*

    Nix da 😃 Das geht auch mit std::vector:

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <cassert>
    
    int main()
    {
        std::vector<char> image;
        std::ifstream file("asd.bmp", std::ios::ate | std::ios::binary);
        assert(file);
        unsigned int filesize = file.tellg();
        file.seekg(0);
        // ...
        image.reserve(filesize);
        file.read(&image[0], filesize);
        // ...
        std::ofstream fout("copy.bmp", std::ios::binary);
        assert(file);
        fout.write(&image[0], filesize);
    }
    

    Und hierbei lässt sich nicht so leicht ein delete[] vergessen.

    mfg.



  • Hab vor ein paar Tagen einen einfachen Laufzeittest mit array vs. vector gemacht (eben wegen Bilddaten).
    Probiert das mal bitte aus und sagt mir, welcher Zeitunterschied bei euch rauskommt. Bei mir war das Array um den Faktor 30(!) schneller.
    Deswegen hab ich mich erstmal für das Array entschieden.
    Aber vielleicht hab ich ja auch falsch gemessen...

    #include <iostream>
    #include <vector>
    #include <windows.h>
    
    using namespace std;
    
    void arr(int size)
    {
    	int* myArray = new int[size];
    
    	for(int i=0; i<size; i++)
    		myArray[i] = 1;
    
    	for(int j=0; j<size; j++)
    		myArray[j] *= 3;
    
    	delete[] myArray;
    }
    
    void vec(int size)
    {
    	vector<int>* myVector = new vector<int>;
    
    	for(int i=0; i<size; i++)
    		myVector->push_back(i);
    
    	for(int j=0; j<size; j++)
    		(*myVector)[j] *= 3;
    
    	delete myVector;
    }
    
    void wait()
    {
    	cin.clear();
    	cin.ignore(cin.rdbuf()->in_avail());
    	cin.get();
    }
    
    int main(void)
    {
    	double start = 0, end = 0;
    	double arrayZeiten[10];
    	double vectorZeiten[10];
    
    	for(int i=0; i<10; i++)
    	{
    		start = GetTickCount();
    		arr(300000);
    		end = GetTickCount();
    
    		arrayZeiten[i] = end - start;
    
    		start = GetTickCount();
    		vec(300000);
    		end = GetTickCount();
    
    		vectorZeiten[i] = end - start;
    	}
    
    	double arrayD = 0, vectorD = 0;
    
    	for(i=0; i<10; i++)
    		arrayD += arrayZeiten[i];
    
    	cout << "Array-Zeiten: " << arrayD / 10 << endl;	
    
    	for(i=0; i<10; i++)
    		vectorD += vectorZeiten[i];
    
    	cout << "Vector-Zeiten: " << vectorD / 10 << endl;
    
    	wait();
    
    	return 0;
    }
    

    Würd mich mal interessieren, was bei euch für Werte rauskommen.



  • Du machst mir Spaß, das Array initalisierst du gleich mit der richtigen Größe und den std::vector nicht, schon klar dass der langsamer ist, der muss ja ständig neuen Speicher herscheffeln. Gib dem vector die Größe gleich im Ctor mit.
    Im Übrigen ist es nicht notwendig, den vector selber auf dem Heap anzulegen.



  • DarthZiu schrieb:

    for(int i=0; i<size; i++)
    myArray[i] = 1;

    for(int i=0; i<size; i++)
    myVector->push_back(i);

    Ist aber nicht wirklich das gleiche und push_back wird immer langsamer sein als [i].



  • DarthZiu! Du vergleichst einen statischen "Container" mit einem dynamischen Container. Ehm, das passt doch irgendwie nicht. Denn das Array kann in der Form einfach nicht das leisten, was vector leisten kann. Wenn dann müsstest du mit Array die gleich Funktionalität nachbilden: bei jeder Index-Erhöhung das selbst Array resizen. Mal schauen wie schnell du dann bist.

    Der Vector spielt dann seinen Vorteil aus, wenn dir beim Anlegen des Containers die Endgröße unbekannt ist. Da kannst du noch soviele Performancetests machen, da wird jeder vector (wenn er vernünftig implementiert ist) sehr gute Arbeit leisten.

    Ansonst kann man auch mit reserve()-Methode nach der Vector-Konstruktion die Laufzeit für das push_back drastisch runter drücken. Dann reserviert der Vector schon mal Speicher vor und du kannst trotzdem mit push_back arbeiten, weil die size() dann unabhängig vom reserve() arbeitet. Bei GPC-Vorschlag wäre size() allerdings gleich zu Anfang >0. Dann würde man anstatt push_back() den []-Op oder at() benutzen (wobei at() sicherer gg. Bufferoverflows ist, aber etwas langsamer, ggü. dem unsicheren []-Op).

    Man muß einfach nur wissen, wie man vector benutzt, dann arbeitet dieser optimal und sicherer als jedes rohe Array.



  • void vec(int size)
    {
    	vector<int>* myVector = new vector<int>(size);
    
    	for(int i=0; i<size; i++)
    		(*myVector)[i] = i;
    
    	for(int j=0; j<size; j++)
    		(*myVector)[j] *= 3;
    
    	delete myVector;
    }
    

    Ist das jetzt richtig (effektiv)? Immer noch Faktor 10 langsamer als das Array.



  • Artchi schrieb:

    Man muß einfach nur wissen, wie man vector benutzt, dann arbeitet dieser optimal und sicherer als jedes rohe Array.

    Dass ein vector sicherer und komfortabler als ein array ist, ist mir klar. Ich benutze vectoren auch so oft wie möglich.
    Mein Problem ist aber, dass ich eine ziemliche Datenmenge (bis zu 20 Bilder pro Sekunde - in einer Auflösung von mindestens 640x480 (307200 Byte-Werte)) erfassen und verarbeiten muss.
    Hier wollte ich ebenfalls vector benutzen und habe deswegen diesen "Performance-Test" gemacht. Aber einen Zeitaufwand, der 5 bis 10 mal höher ist, kann ich mir an dieser Stelle einfach nicht leisten.
    Das ist der Grund meines ersten Posts.

    PS: Vielleicht drücken wir den Zeitaufwand mit weiteren Verbesserungsvorschlägen ja noch auf einen annehmbaren Wert. 👍



  • Schon mal versucht das std::vector-Objekt auf dem Stack statt auf dem Heap anzulegen? Dadurch, daß du über einen Zeiger auf dein Objekt zugreifst, hast du eine zusätzliche Indirektion, die Zeit kostet. Kann allerdings auch sein, daß das wegoptimiert wird (dazu wäre es interessant zu wissen mit welchen Optimierungs-Optionen du kompilierst).


Anmelden zum Antworten