Kann ich davon ausgehen, dass Allokatoren ihren Speicherpool nicht direkt halten (und daher kopiert werden können)?

StackOverflow https://stackoverflow.com//questions/11703643

  •  13-12-2019
  •  | 
  •  

Frage

Ich schreibe einen Container und möchte dem Benutzer die Verwendung benutzerdefinierter Allokatoren erlauben, kann aber nicht sagen, ob ich Allokatoren als Referenz oder als Wert weitergeben soll.

Ist es garantiert (oder zumindest eine vernünftige Annahme), dass ein Allokatorobjekt dies tut? nicht seinen Speicherpool direkt enthalten, und daher wäre es in Ordnung, einen Allokator zu kopieren und zu erwarten, dass die Speicherpools der Allokatoren kreuzkompatibel sind?Oder muss ich Allokatoren immer als Referenz übergeben?

(Ich habe herausgefunden, dass die Übergabe als Referenz die Leistung um einen Faktor von > 2 beeinträchtigt, weil der Compiler anfängt, sich Gedanken über Aliasing zu machen. Es stellt also eine Frage dar, ob ich mich auf diese Annahme verlassen kann oder nicht.)

War es hilfreich?

Lösung

in c ++ 11 § 17.6.3.5 Alllocator Anforderungen [Allocator.Requirements] Gibt die Anforderungen an die Konformen von Zutreiber an. Unter den Anforderungen sind:

generasacodicetagpre.

d. H. Wenn Sie einen Allocator kopieren, müssen die beiden Kopien in der Lage sein, die Zeiger des anderen löschen zu können.

denkbar könnte man interne Puffer in Allocatoren setzen, aber Kopien müssten jedoch eine Liste der Puffer anderer halten. Oder vielleicht könnte ein Allocator einen Invarianten haben, dass die DealLocation immer ein No-Op ist, da der Zeiger immer von einem internen Puffer stammt (entweder von eigener oder von einer anderen Kopie).

Aber was auch immer das Schema, Kopien müssen "cross-kompatibel" sein.

update

Hier ist ein C ++ - 11-konformer Zuschauer, der die "kurze String-Optimierung" enthält. Um es C ++ 11 zu erstellen, musste ich den "internen" Puffer extern in den Allocator legen, damit Kopien gleich sind:

generasacodicetagpre.

Es könnte so verwendet werden:

generasacodicetagpre.

Alle Zuweisungen für das obige Problem werden aus dem örtlichen Gattungsgradiceticetagcode gezeichnet, der 1 KB groß ist. Sie sollten in der Lage sein, diesen Allocator um den Wert oder mit Bezug auf die Verweis zu bestehen.

Andere Tipps

Der alte C++-Standard stellt Anforderungen an einen standardkonformen Allokator:Zu diesen Anforderungen gehört auch das, falls vorhanden Alloc<T> a, b, Dann a == b, und Sie können verwenden b Dinge freigeben, die zugewiesen wurden a.Allokatoren sind grundsätzlich staatenlos.


In C++11 ist die Situation viel komplizierter geworden, da es jetzt Unterstützung dafür gibt Staatsbürgerlich Allokatoren.Beim Kopieren und Verschieben von Objekten gelten bestimmte Regeln dafür, ob ein Container kopiert oder von einem anderen Container verschoben werden kann, wenn sich die Allokatoren unterscheiden, und wie die Allokatoren kopiert oder verschoben werden.

Nur um deine Frage zunächst zu beantworten:Nein, das können Sie auf jeden Fall nicht Gehen Sie davon aus, dass es sinnvoll ist, Ihren Allokator zu kopieren, und Ihr Allokator möglicherweise nicht einmal kopierbar ist.

Hier ist 23.2.1/7 zu diesem Thema:

Sofern nicht anders angegeben, beziehen alle in dieser Klausel definierten Container Speicher mithilfe eines Allokators (siehe 17.6.3.5).Kopierkonstruktoren für diese Containertypen erhalten durch Aufruf einen Allokator allocator_traits<allocator_-type>::select_on_container_copy_construction auf ihre ersten Parameter.Move-Konstruktoren erhalten einen Allokator durch Move-Konstruktion aus dem Allokator, der zum zu verschiebenden Container gehört.Eine solche Verschiebungskonstruktion des Allokators darf nicht über eine Ausnahme beendet werden.Alle anderen Konstruktoren für diese Containertypen benötigen eine Allocator& Argument (17.6.3.5), ein Allokator, dessen Werttyp mit dem Werttyp des Containers übereinstimmt.[Notiz:Wenn ein Aufruf eines Konstruktors den Standardwert eines optionalen Allocator-Arguments verwendet, muss der Allocator-Typ die Wertinitialisierung unterstützen.—Endnote] Eine Kopie dieses Allokators wird für jede Speicherzuweisung verwendet, die von diesen Konstruktoren und allen Mitgliedsfunktionen während der Lebensdauer jedes Containerobjekts oder bis zum Ersetzen des Allokators durchgeführt wird.Der Allokator kann nur durch Zuordnung oder Swap () ersetzt werden.Der Allokatoraustausch erfolgt nur dann durch Kopierzuweisung, Verschiebungszuweisung oder Austausch des Allokators allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value, allocator_traits<allocator_type>::propagate_on_container_move_assignment::value, oder allocator_traits<allocator_type>::propagate_on_container_swap::value ist innerhalb der Implementierung der entsprechenden Containeroperation wahr.Das Verhalten eines Aufrufs der Swap-Funktion eines Containers ist undefiniert, es sei denn, die auszutauschenden Objekte verfügen über Allokatoren, die gleich oder vergleichen allocator_traits<allocator_type>::propagate_on_container_swap::value ist wahr.In allen in dieser Klausel definierten Containertypen ist das Mitglied get_allocator() gibt eine Kopie des Allokators zurück, der zum Erstellen des Containers verwendet wurde, oder, wenn dieser Allokator ersetzt wurde, eine Kopie der letzten Ersetzung.

Siehe auch die Dokumentation von std::allocator_traits für eine Zusammenfassung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top