2016-06-02 2 views
2

Hier habe ich einen einfachen multi_index Container und ich frage mich, ob es eine Möglichkeit ist, die multi_index zwingen die Elemente aneinander angrenzend in Speicher zuzuweisen. Ich dachte, das wäre möglich, wenn der Hauptindex random_access ist.Ist es möglich, multi_index Container zusammenhängende Speicher verwenden?

jedoch Dieses einfache Beispiel zeigt, dass überraschenderweise die Elemente im Speicher nicht zusammenhängend sind. Gibt es eine Kombination aus boost::multi_index::indexed_by, die wahrscheinlich in zusammenhängenden Speicher führen würde?

#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/ordered_index.hpp> 
#include <boost/multi_index/member.hpp> 
#include <boost/multi_index/ordered_index.hpp> 
#include <boost/multi_index/random_access_index.hpp> 

int main(){ 
    typedef boost::multi_index_container< 
     double, // simply store doubles 
     boost::multi_index::indexed_by< 
      boost::multi_index::random_access<> 
     > 
    > random_access_container; 

    random_access_container v; // fill container 
    v.reserve(10); // also tried this 
    v.push_back(1.); 
    v.push_back(2.); 
    v.push_back(3.); 

    assert(v[0] == 1.); // ok 
    assert(*(&v[0] + 1) == v[1]); // this fails, memory is not contiguous 
} 

Anmerkung 1: Das möchte ich für die Kompatibilität (so nutzen multi_index Behälter --with anderen Zugang Optionen- Ich kann), sondern auch den direkten Speicherzugriff verwenden (wie es mit std::vector möglich ist).

ANMERKUNG 2: Ich habe gerade dieses Zitat von der Dokumentation, http://www.boost.org/doc/libs/1_61_0/libs/multi_index/doc/reference/rnd_indices.html#rnd_indices, so dass es schaut schwierig.

Soweit nicht anders angegeben, oder wenn die entsprechende Schnittstelle nicht vorhanden, Random Access Indizes die gleichen Container Anforderungen wie std :: vector und die Anforderungen für std :: list spezifische Liste Operationen an [list.ops überprüfen ]. Einige der wichtigsten Unterschiede mit Bezug auf std :: vector sind:

  1. Random Access Indizes bieten keine Speicher contiguity und somit keine Datenelementfunktionen haben.

    ...

Antwort

2

Nein, Sie haben keinen Speicher Kontiguität. Das Layout eines Schreib-Lese-Index ist vergleichbar mit dem von boost::container::stable_vector:

random-access index memory layout

Eine Annäherung an zusammenhängenden Speicher erhalten werden kann, wenn Sie Ihre Elemente speichern (vom Typ sagen T) in einem std::vector<T> und dann verwenden multi_index_container von std::ref<T> s. Dies erschwert natürlich das Management der Objektlebensdauer.

Edit: Design rationale

Es gibt eine Reihe von Gründen, warum contiguity Speicher ist schwer/stark in der Gestaltung der Bibliothek enthalten:

  • Iterator Stabilität von allen Indizes zur Verfügung gestellt, nicht nur zufällig zugängliche. Es wäre unmöglich, dies (mit angemessener Leistung) zu halten, wenn Elemente zusammenhängend in einem Stück Speicher gespeichert wären.
  • Angenommen, wir haben es irgendwie geschafft, einen Random-Access-Index zu erhalten, der Speicherkontiguität in Bezug auf den Elementspeicher induziert. Was würde passieren, wenn wir zwei Schreib-Lese-Indizes? Es scheint so, als ob der erste Index des Containers einen besonderen Status haben sollte, um das Layout des gesamten Containers zu diktieren, damit er Wasser hält.
  • Nicht zufällige Zugriffsindizes sind notwendigerweise knotenbasiert.Dies bedeutet, dass jeder Wert in einer größeren Struktur mit Platz für zusätzliche Informationen gespeichert wird (rb-tree Zeiger usw.) Wenn Elemente zusammenhängend gespeichert würden, dann wären dies entweder a) die Knoten, die zusammenhängend gespeichert werden, nicht die Werte selbst , was ziemlich nutzlos erscheint (denke, was data() zurückgeben würde), oder b) die Knoten würden von den Werten getrennt werden müssen, so dass, anstatt den Wert in den Knoten einzubetten, Knoten mit Zeigern auf die zusammenhängend gespeicherten Werte hätten Dies ist eine Verschwendung von Raum und sieht nicht wie eine vernünftige Standardentscheidung aus.
+0

Ist das, weil (Iterator) Stabilität eine Priorität im Design hatte? Im Prinzip kann die Reservefunktion dies erreichen, aber ich denke, es hätte die Implementierung enorm erschwert, oder? – alfC

+0

Ich meine mit anderen Worten, warum 'stable_vector' (oder' multi_index') zusammenhängende Speicher (für Knoten) nicht reservieren würde, wenn die Anzahl der Elemente im Voraus bekannt ist? (Ich versuche zu sehen, ob es einen Umstand gibt, bei dem die Erinnerung ausgetrickst werden kann, ich suche nicht nach einer Garantie unter allen Bedingungen.) – alfC

+1

Ich habe meiner Antwort einige Kommentare hinzugefügt, die hoffentlich deine Fragen beantworten. –

Verwandte Themen