2017-03-23 3 views
3

Ich habe die folgenden API-Design-Problem, oder vielmehr dilemma.Ich suche eine Möglichkeit, einige Objekte in STL vector als Objekt zu speichern.Ja, suche ich nach einer Möglichkeit, Vektor-Traversing-Performance durch cache locality Verbesserung zu erhöhen. Nun ist die Sache, diese Art von Objekt sollte auch als nicht kopierbar für den Benutzer der API offen gelegt werden. Und ich meine implizite Kopie über Kopierkonstruktor oder Zuweisung. Aber wie Sie sicher wissen, etwas zu tun, wie folgt aus:Implizite Objektkopie selektiv deaktivieren

#define PREVENT_COPY(TypeName)  \ 
    TypeName (const TypeName &);  \ 
    void operator= (const TypeName &); 
#endif 

class FooClass 
{ 
PREVENT_COPY(FooClass) 
public: 
    FooClass() {} 
~FooClass() {} 
}; 

Und dann:

int main(int argc,char* argv[]) 
{ 
    std::vector<FooClass> fooVec; 
} 

Wird nicht funktionieren, weil der Vektor ideal Zugriff auf copy constructor .So erfordert, ich möchte zu genießen In beiden Welten ist es möglich, den öffentlichen Zugriff auf den Kopier-/Zuweisungsmechanismus zu verhindern und gleichzeitig Objekte in den Vektor zu schieben. C-Array kann STL-Vektor ersetzen. Aber gibt es einen Hack, um es auch mit std :: vector in einem solchen Szenario zu arbeiten?

Als Randbemerkung: Der Grund, warum ich brauche für diese Art von Objekt implizit Kopie zu deaktivieren ist, dass es durch ein internes System verwaltet erstellt und ist, die für den gesamten Lebenszyklus von Objekten dieses Typs verantwortlich ist .Und derzeit cache ich diese in einem Vektor von Zeigern. Das Ziel sind mobile Plattformen und die App ist Echtzeit-Rendering-System. Ich möchte dynamische Zuordnungen zu minimieren und Cache-Lokalität für häufig durchlaufene Vektoren von leistungskritischen Daten zu verbessern.

+2

Mit C++ 11 können Sie Move-Konstruktor verwenden (und weiterhin die Kopie nicht zulassen). – Jarod42

+3

Und 'Freund' erlaubt" selektiv "Zugang zu privaten Methoden zu geben. – Jarod42

+0

Move Konstruktor scheint zu sein, was ich brauche. Nie realisiert, dass es so einfach sein würde –

Antwort

4

Genau dies ist rvalue Referenzen (in C++ 11 eingeführt) sind für. Wenn Sie eine einzelne nicht kopierbare Instanz haben möchten, die Sie von einem Ort zum anderen übertragen, können Sie move-semantics zusammen mit std::vector::emplace_back verwenden.

Zum Beispiel:

#include <iostream> 
#include <vector> 

struct Foo 
{ 
    Foo(int b) : bar(b) {} 

    Foo(const Foo&) = delete; 
    Foo& operator=(const Foo&) = delete; 

    ~Foo() = default; 
    Foo(Foo&& f) = default; 
    Foo & operator=(Foo &&) = default; 

    int bar; 
}; 


int main() 
{ 
    std::vector<Foo> foos; 
    foos.emplace_back(Foo(4)); 
    Foo f(2); 
    foos.emplace_back(std::move(f)); 
    // Now the contents of 'f' must be considered invalid, and 
    // using 'f' is undefined behavior. 

    for(const Foo & f : foos) 
    { 
     std::cout << f.bar << std::endl; 
    } 
    return 0; 
} 

Ausgang:

4 
2 

Dies ist ein naives Beispiel, weil es trivial Datentypen und in Verzug geratenen Zug-Aufbau verwendet wird. Aber hoffentlich bekommst du das Bild.

+0

Ich sollte darauf hinweisen, dass es auch 'std :: vector :: emplace 'gibt, welches das move-Äquivalent von' std :: vector :: insert' ist. – paddy

+0

'mit 'f' ist undefiniertes Verhalten. "Das ist nicht wahr. Vom Objekt verschobene Objekte befinden sich in den meisten Fällen in einem gültigen, aber nicht spezifizierten Zustand. –

+0

Wenn der Zustand von 'f' nicht spezifiziert ist, dann ist die Logik, die von einem angenommenen Zustand abhängt, undefiniert. – paddy

0

Die Elemente eines Vektors werden zusammenhängend im Speicher gespeichert. Die Sache, die Sie erreichen möchten, ist, separate Objekte, die im Speicher abgelegt sind, in einen Vektor zu schieben. Sie können ein Objekt mithilfe von in einen Vektor verschieben, indem Sie seinen Verschiebungskonstruktor verwenden (standardmäßig). Alle Zeiger, die auf dieses Objekt zeigen, sind jedoch ungültig.

Meiner Meinung nach ist die Verwendung einer poolähnlichen Struktur und das Erstellen Ihrer Objekte im Voraus ein besserer Ansatz in Ihrem Fall.

+0

Daran gedacht. Ein Pool wäre in meinem Fall extrem ineffizient.Die Anzahl der Objekte ist ziemlich dynamisch (man denke an eine Game Engine mit einer variierenden Anzahl von Objekten in einer Szene) und ich interessiere mich auch sehr für den gesamten Speicherbedarf des Prozessspeichers während der Laufzeit. Das Ausführen eines riesigen Pools dieser Objekte wäre eine echte Verschwendung von Speicherplatz . –

+0

Haben Sie überlegt, ein komponentenbasiertes Entitätsmodell zu verwenden? Sie können einen Block von Komponentenobjekten zusammenfassen und bei Bedarf erneut verwenden. – qua

+0

Ich verwende komponentenbasiertes Paradigma. Trotzdem sollte man bei mem pools vorsichtig sein;) –

Verwandte Themen