2017-06-13 3 views
3
std::list<Reader> readers; 

readers.push_back(Reader()); 

Reader& r = *(readers.begin()); 

/* at this point, the exact place in list, where the reader was picked out, is forgotten. 
    Only 'r' shows which element of the list it is. */ 

readers.erase(r); //<---how to do this? 

Clients erhalten die neuen Instanzen 'Leser' Objekte von einem Manager/Dispatcher. Der Verwalter führt eine interne Liste von allem, was gesendet wurde, und macht eine zwischengespeicherte Daten ungültig/frei, wenn "alle Interessierten" sie durch Beobachten des versendeten Leserspools abholen.Element aus Std entfernen :: list by reference

Wenn der Client nicht mehr an den Daten interessiert ist, sollte er den Leser zum Entfernen aus dem Pool an den Manager zurückgeben. Aber ich möchte nicht, dass der Kunde einen Iterator behält - er ist absolut nicht am Mut des Managers und des Pools der Leser interessiert; braucht nur diesen einen eigenen Reader, nicht einen Iterator, der darauf hinweist. Zum Löschen ruft er die Bereinigungsfunktion des Managers mit dem Verweis auf diesen einzelnen Leser auf.

Gibt es eine bessere Möglichkeit, diesen Reader von der Liste zu löschen, als die gesamte Liste auf der Suche nach dem einen Reader zu durchsuchen, zu dem der Verweis führt?

+0

Sind t hese 'Readers' einzigartig (kein' Reader's haben den gleichen Wert)? – NathanOliver

+0

@NathanOliver: Ja. Ein eindeutiger Leser pro Client, mit Methoden, um Daten aus dem Cache zu holen (und sie als "verbraucht von diesem" zu markieren), Manager macht Daten ungültig, wenn sie von allen Interessenten "aufgebraucht" sind. –

+0

'readers.remove (r);' sollte funktionieren (wenn 'r' eindeutig ist), aber die Liste intern iterieren. –

Antwort

3

Ihre Optionen, wenn Sie nur einen Verweis auf das Objekt haben, ist std::list::remove

readers.remove(r); 

oder std::find in Verbindung zu verwenden, um mit std::list::erase

readers.erase(std::find(readers.begin(), readers.end(), r)); 

Ersteres hat die gesamte Liste, während die letztere iterieren stoppt, wenn das erste Element gefunden und dann entfernt wird. Für große Liste kann dies einen großen Unterschied machen.

Diese beiden Optionen funktionieren nur, wenn die Elemente eindeutig sind. Wenn Sie nicht eindeutige Elemente haben, können Sie std::find_if verwenden und einen Funktor bereitstellen, der die Adresse der Elemente vergleicht. Auf diese Weise können Sie garantieren, dass Sie nur das Objekt löschen, auf das sich die Referenz bezieht, anstatt gleich zu vergleichen.

readers.erase(std::find_if(readers.begin(), readers.end(), [&](const auto& e) {return &r == &e;})); 
2

Verwendung std::remove in Kombination mit erase

readers.erase(std::remove(readers.begin(), readers.end(), r), readers.end()); 

Auch kann u nicht Element aus der Liste von Wert löschen, ohne sie iterieren. Wenn Sie darüber nachdenken, macht es nicht einmal Sinn, denn Zeiger innerhalb der Liste müssen auf aktualisiert werden.

+0

' remove' entfernt in diesem Fall. Dies wird nicht kompiliert, da es 'void' zurückgibt. – NathanOliver

+0

das wird nicht gefunden genau dieses Element, aber jedes Element, das Gleichheit ist vergleichbar mit ... Sie müssen die Elems Zeiger vergleichen ... – ovanes

+0

ja Nathan, mein Schlechter, ich aktualisierte die Antwort –

2

können Sie die Zeiger vergleichen, um zu überprüfen, ob sie

readers.remove_if([r=&r](auto& x){return &x==r;}); 
+1

Entfernen erwartet einen Wert, den es mit Elementen in der Liste vergleichen kann. Ziemlich sicher, das wird nicht kompilieren – NathanOliver

+1

Vielleicht meinst du 'remove_if' und nicht' remove'? – Akira

+0

Ändern Sie 'remove' zu' remove_if' und Sie haben die coolste Lösung! – ovanes

1

gleiche Objekt sind die vorstehende Liste gleiche Werte enthalten, dann können Sie so etwas wie die folgenden

#include <iostream> 
#include <list> 

int main() 
{ 
    struct Reader { std::pair<char, int> p; }; 
    std::list<Reader> readers; 

    readers.push_back({{ 'A', 1 } }); 
    readers.push_back({ { 'A', 2 } }); 
    Reader &rr = readers.back(); 
    readers.push_back({ { 'A', 3 } }); 

    readers.remove_if([&rr](const Reader &r) { return &r == &rr; }); 

    for (const auto &r : readers) 
    { 
     std::cout << r.p.first << ' ' << r.p.second << std::endl; 
    } 

    return 0; 
} 

Das Programm tun Ausgabe ist

A 1 
A 3 
Verwandte Themen