C++ std::set update ist mühsam: ich kann nicht ändern, ein element in place
Finde ich die update-operation auf std::set
mühsam, da es keine solche API auf cppreference. Also, was ich derzeit tun, ist so etwas wie dieses:
//find element in set by iterator
Element copy = *iterator;
... //update member value on copy, varies
Set.erase(iterator);
Set.insert(copy);
Grundsätzlich der iterator zurück von Set
ist ein const_iterator
und Sie können nicht ändern, seinen Wert direkt.
Gibt es einen besseren Weg, dies zu tun? Oder vielleicht sollte ich überschreiben std::set
durch meinen eigenen (was ich nicht genau weiß, wie es funktioniert..)
- Eine inline-Funktion, wenn Sie finden über 2 Aussagen ist schon mühsam.
- KennyTM trifft den Nagel auf den Kopf. Es gibt keine Nachteile performancewise, um dies zu tun, so tun Sie es einfach jetzt schon! 😛
- Wenn Sie schreiben, eine update-Funktion, möchten Sie vielleicht, um das Modell auf die gleiche Weise, wie Boost.MultiIndex: boost.org/doc/libs/release/libs/multi_index/doc/tutorial/...
- cplusplus.com ist eine schreckliche Referenz. Finden Aspekte der Sprache "langweilig", weil es scheint... seltsam.
- Ich denke der Nachteil dieses Ansatzes ist, wobei ein Lese/Schreib-Sperre im Fall der gleichzeitigen Verarbeitung.
Du musst angemeldet sein, um einen Kommentar abzugeben.
set
zurückconst_iterators
(der standard sagtset<T>::iterator
istconst
, und dassset<T>::const_iterator
undset<T>::iterator
kann in der Tat die gleichen Typ - siehe 23.2.4/6 in n3000.pdf), weil es einen bestellten container. Wenn es wieder eine regelmäßigeiterator
, würden Sie erlaubt werden, ändern Sie die Elemente mit dem Wert aus dem Behälter, potenziell änderung der Bestellung.Ihre Lösung ist die idiomatische Weise zu verändern, die Elemente in einer
set
.std::set
nicht zurückconst_iterator
und Sie kann ändern Sie die Elemente, wenn du vorsichtig bist. Warum ist diese (falsche) Antwort immer so viele upvotes? Was bin ich?set
undmap
müssen unveränderlich Schlüssel, und wenn Sie nicht-Schlüssel-Felder, die Sie ändern möchten, diese sollte den Wert Teil einermap
. (Ich muss Optionen, wie mit dermutable
Mitglieder inset
Elemente: igitt)Gibt es 2 Möglichkeiten, dies zu tun, in der einfache Fall:
mutable
auf die variable, die nicht Teil des SchlüsselsKey
Value
- pair-Mädchen (und verwenden Sie einstd::map
)Nun, die Frage ist für den kniffligen Fall: was passiert, wenn das update ändert die
key
Teil des Objekts ? Dein Ansatz funktioniert, obwohl ich zugeben, es ist mühsam.Update: Obwohl das folgende gilt jetzt, das Verhalten wird als eine defekt und wird geändert werden in der kommenden version des Standards. Wie sehr traurig.
Gibt es mehrere Punkte, die Ihre Frage ziemlich verwirrend.
std::set
ist eine Klasse, und kann deshalb nicht etwas zurückzugeben.s.erase(iter)
, danniter
ist nicht einconst_iterator
.erase
erfordert eine nicht-const-iterator.std::set
, die zurück einen iterator zurückgeben, einen nicht-const-iterator solange das set ist non-const-als auch.Dürfen Sie zum ändern des Werts eines Elements in einem Satz, solange das update nicht die Anordnung der Elemente ändern. Der folgende code kompiliert und funktioniert Prima.
Wenn Ihr update ändert die Reihenfolge der Elemente, dann Sie haben zu löschen und wieder einzufügen.
pair<const Key, T>
. Auf dieser Grundlage dürfen, ändern Sie die set-Taste scheint wie ein versehen, dass der C++0x-Ausschuss fest.*iter = 0;
? Hat der Betrieb zu werfen? Tut es ermöglicht die Bedienung aber zu Problemen im weiteren Gebrauch der container?In C++17, die Sie tun können, besser mit
extract()
, Dank P0083:Dadurch vermeiden Sie eine zusätzliche Kopie Ihrer Art und eine extra allocation/deallocation, und auch mit move-nur Typen.
Können Sie auch
extract
durch Schlüssel. Wenn der Schlüssel nicht vorhanden ist, wird das Ergebnis eine leere Knoten:Die Sie möglicherweise verwenden möchten, ein
std::map
statt. Verwenden Sie den Teil derElement
betrifft die Bestellung der Schlüssel, und alleElement
als Wert. Wird es einige kleinere die Duplizierung der Daten, aber haben Sie einfacher (und wahrscheinlich schneller) aktualisiert.Begegnete ich das gleiche Thema in C++11, wo in der Tat
::std::set<T>::iterator
ist konstant und somit nicht erlaubt, den Inhalt ändern, auch wenn wir wissen, dass die transformation nicht auf die<
invariant. Sie können dies umgehen, indem er::std::set
in einemutable_set
geben, oder schreiben Sie ein wrapper für den Inhalt:Ich finde das viel einfacher und es funktioniert in 90% der Fälle, ohne dass der Benutzer auch merken das es etwas zwischen der eingestellten und der tatsächlichen Typ.
Dies ist schneller, in einigen Fällen:
Wenn der Wert in der Regel nicht schon in der
std::set
dann kann dies die bessere Leistung.