sizeof(int) 4 bytes, im Taskmanager ~17 bytes



  • Naja, ich habe gelesen, dass der Heap viel größer ist als der Stack, und da ich vor habe über eine Millionen Knoten anzulegen, zu jedem Knoten mehrere Kanten anzulegen und dann zu durchsuchen... Nunja, ich dachte da sei es eine bessere Idee das auf den Heap zu packen.

    Ich werde mich mal um ein wenig Bücher zu c++ bemühen.

    Danke.


  • Administrator

    muuh schrieb:

    Naja, ich habe gelesen, dass der Heap viel größer ist als der Stack, und da ich vor habe über eine Millionen Knoten anzulegen, zu jedem Knoten mehrere Kanten anzulegen und dann zu durchsuchen... Nunja, ich dachte da sei es eine bessere Idee das auf den Heap zu packen.

    Die Sache ist aber, dass std::list einen Defaultallokator intern benutzt. Das std::list Objekt bleibt immer gleich gross, egal wieviele Objekte du reinstopfst, denn std::list setzt diese intern über den Defaultallokator auf den Heap. Aber sowas lernt man in einem guten C++ Buch 😉

    Grüssli



  • muuh schrieb:

    Naja, ich habe gelesen, dass der Heap viel größer ist als der Stack, und da ich vor habe über eine Millionen Knoten anzulegen, zu jedem Knoten mehrere Kanten anzulegen und dann zu durchsuchen... Nunja, ich dachte da sei es eine bessere Idee das auf den Heap zu packen.

    std::list und die anderen STL-Container verwenden alle intern den Heap, du bekommst davon einfach nichts mit und hast dich nicht ums Freigeben zu kümmern.

    Aber ich kann Dravere nur zustimmen: Die Konzepte von C++ sind in vieler Hinsicht sehr speziell. Ein Neu-Lernen bringt mehr als ein Umlernen, denn die Gemeinsamkeiten hören schon bald einmal auf...



  • muuh schrieb:

    Naja, ich habe gelesen, dass der Heap viel größer ist als der Stack, und da ich vor habe über eine Millionen Knoten anzulegen, zu jedem Knoten mehrere Kanten anzulegen und dann zu durchsuchen... Nunja, ich dachte da sei es eine bessere Idee das auf den Heap zu packen.

    Wenn du sowas schreibst:

    myList.push_back(Node(x,y,z));
    

    passiert folgendes:

    1. ein Node-Objekt wird auf dem Stack angelegt.
    2. die Memberfunktion push_back wird auf myList aufgerufen, ihr wird dieses Node-Objekt per Referenz übergeben
    3. push_back erzeugt einen Listenknoten auf dem Heap und kopiert das übergebene Node-Objekt dort rein
    4. das in Schritt 1 erzeugte Node-Objekt wird, da es ein temporäres Objekt ist, am Ende des Statements zerstört (sonst bei Verlassen des Scopes)

    es existiert jetzt nur noch ein Node als Teil eines Listenknotens auf dem Heap.



  • Advanced C++ hat nen schönes Beispiel mit Erklärung für einen Small-Object-Allocator.



  • Ah, das ist cool, danke für eure Hilfe.



  • Eine Frage hätte ich doch noch:

    Test 1:
    Eine Millionen Knoten in einen vector speichern.
    Knoten haben 6 integer (24 byte).
    Speicherverbrauch ~25 mb.

    Test 2:
    Eine Millionen Knoten in einen vector speichern.
    Knoten haben einen vector (24 byte).
    Speicherverbrauch ~41 mb.

    Woran liegt das?



  • Sehrwahrscheinlich liegt es daran, dass der std::vector ein wenig Speicher auf Vorrat allokiert, um besseres Laufzeitverhalten zu erzeugen. Bei vielen kleinen Containern macht das etwas aus.

    Um mehr zu sagen, müsstest du uns den Code zeigen und sagen, wieviel bei dir sizeof des jeweiligen Elementtypen ausgibt. Eventuell spielt Alignment auch noch eine Rolle.



  • Test 1:

    class Node
    {
    private:
    	int a;
    	int b;
    	int c;
    	int d;
    	int e;
    	int f;
    
    public:
    	Node();
    	~ Node();
    };
    
    Node:: Node()
    {
    
    }
    
    Node::~ Node()
    {
    
    }
    
    int main(int agc, char* argv[])
    {
    	std::vector< Node > field;
    	for (int i = 0; i < 1000000; i++)
    	{
    		field.push_back(Node());
    	}
    	std::cout<<sizeof(Node)<<std::endl;
    	std::cout<<sizeof(int)<<std::endl;
    	std::cin.get();
    	return 0;
    }
    

    Die Ausgabe ist:
    24
    4

    taskmanager: 25192 kb

    Und Test 2:

    class Node
    {
    private:
    	std::vector<int> myVec;
    
    public:
    	Node();
    	~ Node();
    };
    
    Node:: Node()
    {
    
    }
    
    Node::~ Node()
    {
    
    }
    
    int main(int agc, char* argv[])
    {
    	std::vector< Node > field;
    	for (int i = 0; i < 1000000; i++)
    	{
    		field.push_back(Knoten());
    	}
    	std::cout<<sizeof(Node)<<std::endl;
    	std::cout<<sizeof(std::vector<int>)<<std::endl;
    	std::cin.get();
    	return 0;
    }
    

    Die Ausgabe ist:
    24
    24

    Taskmanager: 40856 kb



  • Was denkst Du mit sizeof(std::vector<int>) zu messen?
    Simon



  • Den Speicher den myVec belegt.
    myVec.capacity() ist übrigens 0.



  • theta schrieb:

    Was denkst Du mit sizeof(std::vector<int>) zu messen?
    Simon

    Da er den std::vector<int> nicht füllt, sollte das bereits die gesamte Grösse sein.

    muuh schrieb:

    Den Speicher den myVec belegt.

    Vorsicht, sizeof gibt nur nur die Grösse des Objekts (zur Compilezeit) Bescheid und sagt nichts über den tatsächlichen Speicherverbrauch aus.



  • **@muuh:**Aus reiner Neugier: Welchen Wert vermutest Du für s?

    struct Object
    {
    	Object() : value(0) {}
    	long* value;
    };
    
    int main()
    {
    	Object object;
    	object.value = new long[256];
    
    	size_t s = sizeof(object);
    
    	delete[] object.value;	
    }
    

    Simon



  • muuh, was sagt capacity() zu den grossen Vectoren aus? Sind beide gleich?



  • @ theta: Kein Schimmer, der Pointer wird wohl 4 sein. Ich weiss nicht was Object() : value(0) {} darstellt, daher tipp ich einfach mal auf 4.

    @ Nexus: 1049869 wird in beiden Fällen für field.capacity() angezeigt.


Anmelden zum Antworten