2016-03-29 16 views
0

Das folgende Stück Code kompiliert und läuft gut, aber ich habe gelesen auf reinterpret_cast und ich kann nicht wirklich ausmachen, wenn es Standard-kompatibel und ist tragbar. In meinem Kopf sollte es sein, da wir explizit den zugrunde liegenden Container der priority_queue angeben, aber ich konnte keine direkte Antwort bekommen, sodass SO-Assistenten einen Einblick in dieses Stück haben könnten.Wird reinterpret_cast auf priority_queue durch den zugrunde liegenden Vektor nicht-Standard durchlaufen?

Was es tut, ist im Grunde eine priority_queue erstellen, die mit Ganzzahlen mit einem Vektor beschäftigt. Diese Warteschlange wird dann in einen Vektorzeiger neuinterpretiert, so dass die Elemente der Warteschlange durchlaufen werden können (da die Prioritätswarteschlange diese Funktionalität nicht selbst enthält).

#include <iostream> 
#include <vector> 
#include <queue> 


int main() { 
    std::priority_queue< int, std::vector<int> > pq; 

    pq.push(100); 
    pq.push(32); 
    pq.push(1); 

    auto o = reinterpret_cast<std::vector<int> *>(&pq); 
    for (std::vector<int>::iterator it = (*o).begin(); it != (*o).end(); it++) { 
     std::cout << (*it) << std::endl; 
    } 

    return 0; 
} 

Antwort

2

Der Standard übernimmt keine Garantie über die Layout der std::priority_queue Klasse. Wenn dies bei Ihrer Implementierung funktioniert, muss es daran liegen, dass die std::vector am Anfang des std::priority_queue Objekts gespeichert ist, aber das kann sicher nicht verlässlich sein.

Die richtige Sache zu tun ist, eine eigene Variante von std::priority_queue (der <algorithm> Header enthält bereits die notwendigen Heap-Algorithmen, wie std::push_heap) schreiben oder eine Klasse von std::priority_queue, abzuleiten, die Sie c Zugriff auf das geschützte Element gibt, das bezieht sich zu dem zugrunde liegenden Container.

0

Das folgende Stück Code kompiliert und läuft ganz gut

puh! Das war Glück.

aber ich habe auf reinterpret_cast lesen und ich kann wirklich nicht machen, wenn es Standard ist konform

ja es

ist

und ist tragbar.

fast nie. sicherlich nicht die Art, wie Sie es benutzen. Es ist einer von denen "wenn Sie nicht genau wissen, wie es funktioniert, berühren Sie es nicht" Dinge.

Sie können portably umdeuten einen Gipsverband * auf einen void * und zurück * zu einem A ... als das ist es (OK, es gibt ein paar mehr Anwendungsfälle, aber sie sind spezifische und Sie brauchen um sie zu kennen, bevor Sie mit diesem speziellen Sprengstoff spielen).

In meinem Kopf sollte es sein, da wir explizit den zugrunde liegenden Container der priority_queue angeben, aber ich konnte keine direkte Antwort bekommen, so dass SO-Assistenten einen Einblick in dieses Stück haben könnten.

std :: priority_queue ist eine spezifische Anpassung des zugrunde liegenden Containers. Da der ordnungsgemäße Betrieb der Warteschlange davon abhängt, dass Sie den zugrunde liegenden Container nicht manipulieren, wird diese von der Schnittstelle der Warteschlange vorsätzlich vor Ihnen verborgen.

Was es tut, ist im Grunde erstellen Sie eine priority_queue, die mit Ganzzahlen mit einem Vektor beschäftigt.Diese Warteschlange wird dann in einen Vektorzeiger neuinterpretiert, so dass die Elemente der Warteschlange durchlaufen werden können (da die Prioritätswarteschlange diese Funktionalität nicht selbst enthält).

Was es wirklich tut, ist undefinierten Verhalten aufrufen, die es nicht mehr möglich macht, über das Ergebnis irgendeines Teils des Programms zur Vernunft. Wenn es in Ihrer Umgebung funktioniert hat, ist das eine Schande. Denn jetzt wirst du versucht sein, es in meiner zu veröffentlichen, wo es wahrscheinlich nicht oder vielleicht für eine Weile bleibt - während es still mein Gedächtnis verschmutzt, bis ... BOOM! mein Prozess Kern Dumps und wir sind alle ahnungslos, warum.