Speicheradressen in Schleifen



  • Hi,

    for (int i = 0; i < 10; i++) {
        std::pair<int, int> pair = std::make_pair(i, i+1);
        std::cout << &pair << std::endl;
    }
    

    liefert mir als Ausgabe:

    0x7fffa6ff6ee0                                       
    0x7fffa6ff6ee0                                       
    0x7fffa6ff6ee0                                       
    0x7fffa6ff6ee0                                       
    0x7fffa6ff6ee0                                       
    0x7fffa6ff6ee0                                       
    0x7fffa6ff6ee0                                       
    0x7fffa6ff6ee0                                       
    0x7fffa6ff6ee0                                       
    0x7fffa6ff6ee0
    

    d.h., die in der for-Schleife erzeugten pair-Objekte werden wohl alle an die gleiche Stelle im Speicher abgelegt.
    Ist es möglich, dass die Objekte jeweils eine andere Speicheradresse zugewiesen bekommen? Konkret möchte ich in etwa sowas machen:

    std::priority_queue<pair<int, int>*, vector<pair<int, int>* >, compare_pairs> pq;
    for (...)
    {
      std::pair<int, int> pair = std::make_pair(i, i+1);
      pq.push(&pair);
      ...
    }
    

    mit

    struct compare_pairs
    {
      bool operator()(const pair<int, int>* a, const pair<int, int>* b)
      const
      {
        if (a->second == b->second) return a->first > b->first;
        return a->second < b->second;
      }
    };
    

    Die Reihenfolge der pair-Objekte in der priority-queue entspricht aber überhaupt nicht der gewünschten Reihenfolge (weil eben immer nur auf die eine Speicheradresse zugegriffen wird?)
    Jemand ne Idee?



  • Warum überhaupt Zeiger? Benutze lediglich std::pair<int, int> . Ein operator< wird übrigens auch schon von std::pair bereitgestellt.

    Und Zeiger auf lokale Variablen werden ungültig, sobald der Block verlassen wird (also nach jedem Schleifendurchgang). Dein zweiter Code resultiert daher in undefiniertem Verhalten.



  • Nexus schrieb:

    Warum überhaupt Zeiger? Benutze lediglich std::pair<int, int> . Ein operator< wird übrigens auch schon von std::pair bereitgestellt.

    Und Zeiger auf lokale Variablen werden ungültig, sobald der Block verlassen wird (also nach jedem Schleifendurchgang). Dein zweiter Code resultiert daher in undefiniertem Verhalten.

    Weil ich es möglichst performant programmieren möchte und sehr viele pair-Objekte erzeuge. War/bin der Meinung, dass das mit Zeigern schneller geht. Insbesondere bei pq.push(&pair); sollte das schon Vorteile bringen, da keine Kopie des pair-Objektes erzeugt werden muss.



  • rotzenplotz schrieb:

    Weil ich es möglichst performant programmieren möchte und sehr viele pair-Objekte erzeuge. War/bin der Meinung, dass das mit Zeigern schneller geht.

    Ich kann immer noch nicht verstehen, warum so viele Leute sich mühsamen, fehlerhaften Code zurechtfrickeln mit der Begründung, sie seien auf die Performance angewiesen. Dein Post ist ein Musterbeispiel für Premature Optimization.

    Zeiger sind gerade bei pair<int, int> nicht schneller. Im Gegenteil. Ein Zeiger ist selbst wahrscheinlich gleich gross wie ein int , der gesparte Kopieraufwand hält sich also in Grenzen. Im Gegenzug kommt die dauernde Dereferenzierung dazu. Und falls du das Ganze noch korrekt programmieren würdest, hättest du dynamische Speicherverwaltung, was den Overhead pro std::pair erst recht in die Höhe schiessen lässt.

    rotzenplotz schrieb:

    Insbesondere bei pq.push(&pair); sollte das schon Vorteile bringen, da keine Kopie des pair-Objektes erzeugt werden muss.

    Schau dir nochmals an, wie das mit Gültigkeitsbereichen funktioniert. Der Code ist wie gesagt fehlerhaft.

    Bitte tu uns allen einen Gefallen und verwende Kopien. Der Code wird übersichtlicher, korrekter und zudem schneller.



  • Wenn die Dinger nicht kopiert werden sollen, erstell doch ein Array auf dem Stack.



  • Nexus schrieb:

    rotzenplotz schrieb:

    Weil ich es möglichst performant programmieren möchte und sehr viele pair-Objekte erzeuge. War/bin der Meinung, dass das mit Zeigern schneller geht.

    Ich kann immer noch nicht verstehen, warum so viele Leute sich mühsamen, fehlerhaften Code zurechtfrickeln mit der Begründung, sie seien auf die Performance angewiesen. Dein Post ist ein Musterbeispiel für Premature Optimization.

    Zeiger sind gerade bei pair<int, int> nicht schneller. Im Gegenteil. Ein Zeiger ist selbst wahrscheinlich gleich gross wie ein int , der gesparte Kopieraufwand hält sich also in Grenzen. Im Gegenzug kommt die dauernde Dereferenzierung dazu. Und falls du das Ganze noch korrekt programmieren würdest, hättest du dynamische Speicherverwaltung, was den Overhead pro std::pair erst recht in die Höhe schiessen lässt.

    rotzenplotz schrieb:

    Insbesondere bei pq.push(&pair); sollte das schon Vorteile bringen, da keine Kopie des pair-Objektes erzeugt werden muss.

    Schau dir nochmals an, wie das mit Gültigkeitsbereichen funktioniert. Der Code ist wie gesagt fehlerhaft.

    Bitte tu uns allen einen Gefallen und verwende Kopien. Der Code wird übersichtlicher, korrekter und zudem schneller.

    Naja, zu dem Thema, wie der Code letztendlich aussehen soll, gibt's wahrscheinlich viele Meinungen. Aber wenn man es halt so lernt, dass man für alles was über primitive Datentypen hinausgeht, Zeiger verwenden sollte, versucht man es natürlich auch so zu machen. Werde mich weiter schlau machen - dir danke für deine Mühe.



  • rotzenplotz schrieb:

    Naja, zu dem Thema, wie der Code letztendlich aussehen soll, gibt's wahrscheinlich viele Meinungen.

    Nein, wenn der Code so offensichtlich fehlerhaft ist, sind sich Leute mit Ahnung von C++ ziemlich einig.

    rotzenplotz schrieb:

    Aber wenn man es halt so lernt, dass man für alles was über primitive Datentypen hinausgeht, Zeiger verwenden sollte, versucht man es natürlich auch so zu machen.

    Vergiss das ganz schnell wieder. So pauschal ist das nämlich grober Unfug.


Anmelden zum Antworten