Ist es gefährlich, einen Zeiger aus einem std::map::find
an die Daten zurückzugeben und diesen im Gegensatz zu einer Kopie der Daten zu verwenden?
Momentan erhalte ich einen Zeiger auf einen Eintrag in meiner Map und gebe ihn an eine andere Funktion weiter, um die Daten anzuzeigen. Ich mache mir Sorgen über das Verschieben von Objekten, wodurch der Zeiger ungültig wird. Ist das ein echtes Problem?
Hier ist meine Beispielfunktion:
%Vor%}
Es wäre zweifellos typischer, einen Iterator als einen Zeiger zurückzugeben, obwohl es wahrscheinlich wenig Unterschied macht.
Soweit gültig bleibt: Ein Map-Iterator bleibt solange gültig, bis das Element, auf das es verweist, aus der Map entfernt / gelöscht wird.
Wenn Sie einen anderen -Knoten in die Karte einfügen oder löschen, kann dies dazu führen, dass die Knoten in der Karte neu angeordnet werden. Das geschieht, indem man die Zeiger zwischen den Knoten manipuliert, also ändert er, welche anderen Knoten Zeiger auf den Knoten haben, den Sie interessieren, ändert aber nicht die Adresse oder den Inhalt dieses bestimmten Knotens, so dass Zeiger / Iteratoren für diesen Knoten gültig bleiben / p>
Solange Sie, Ihr Code und Ihr Entwicklungsteam die Lebensdauer der std :: map-Werte verstehen (gültig nach insert
und ungültig nach erase
, clear
, assign
oder operator=
), dann ist die Verwendung von iterator
, const_iterator
, ::mapped_type*
oder ::mapped_type const*
gültig. Wenn die Rückgabe immer garantiert ist, ist auch ::mapped_type&
oder ::mapped_type const&
gültig.
Ich würde die const
-Versionen den mutierbaren Versionen vorziehen, und ich würde Referenzen über Zeigern den Iteratoren vorziehen.
Die Rückgabe eines Iterators gegenüber einem Zeiger ist schlecht:
.second
aufrufen muss, um den tatsächlichen Wert zu erhalten.
.first
ist der Schlüssel, der dem Benutzer nicht wichtig ist. ::end()
, die dem Aufrufer offensichtlich nicht zur Verfügung steht. Es ist nicht gefährlich - der Zeiger bleibt so lange gültig wie ein Iterator oder eine Referenz.
In Ihrem speziellen Fall würde ich jedoch argumentieren, dass es sowieso nicht das Richtige ist. Ihre Funktion gibt bedingungslos ein Ergebnis zurück. Es gibt nie null zurück. Warum also nicht eine Referenz zurückgeben?
Auch einige Kommentare zu Ihrem Code.
%Vor%Warum kombinieren Sie Deklaration und Zuweisung nicht in Initialisierung? Wenn Sie C ++ 11-Unterstützung haben, können Sie einfach
schreiben %Vor%Dann:
%Vor%Sie können das Einfügen mit make_pair vereinfachen. Sie können auch die redundante Suche vermeiden, da insert ein Iterator für das neu eingefügte Element (als erstes Element eines Paares) zurückgibt.
%Vor%Schließlich:
%Vor%Benutze niemals C-Style-Modelle. Es könnte nicht das tun, was Sie erwarten. Benutze auch keine Würfe, wenn sie nicht notwendig sind. & amp; foundStruct- & gt; second hat bereits den Typ MyStruct *, also warum einen Cast einfügen? Die einzige Sache, die es tut, ist, einen Platz zu verstecken, den Sie ändern müssen, wenn Sie jemals den Werttyp Ihrer Karte ändern.
Ja,
Wenn Sie eine generische Funktion erstellen, ohne deren Verwendung zu kennen, kann es gefährlich sein, den Zeiger (oder den Iterator) zurückzugeben, da dieser ungültig werden kann.
Ich würde einen von zweien empfehlen:
1. arbeite mit std :: shared_ptr und gib das zurück. (siehe unten)
2. Rückgabe der Struktur nach Wert (kann langsamer sein)