2016-08-03 17 views
0

Wenn ich eine Struktur für die Darstellung eines Elements machen möchten auf dem Bildschirm zu machen, und enthält:C++: Null-Zeiger und structs

  1. Eine Liste der Eingeborenen „renderables“ (meshes, triangles usw.)
  2. Ein Zeiger auf andere Unterstrukturen

Bedeutet dies:

struct RenderGroup { 
    std::vector<RenderGroup*> Children; 
    std::vector<Renderable> Renderables; 
} 

Was ist der beste Weg, dies zu tun? Und wenn ich keine Unterstrukturen habe, kann ich einfach einen Nullzeiger in den Vektor setzen?

Edit: Bad Tags

+5

Wenn Sie keine Unterstrukturen haben, fügen Sie * nichts * in den Vektor ein. – Galik

+0

Wenn Sie fragen müssen, ob ein Nullzeiger in Ihrem Graphen angebracht ist, haben Sie eine schlechte Zeit. –

Antwort

1

A std::vector ist nicht eine feste Größe, so dass, wenn es keine Elemente drin sind, werden size zurückkehren 0 und leer wird true zurück.

std::vector<int> v; 
auto sz = v.size(); // sz has value 0 
auto e = v.empty(); // true 
v.push_back(42); 
sz = v.size(); // 1 
e = v.emi empty(); // false 

Sie können auch Elemente entfernen (der Vektor alle followingv Elemente bewegt sich die Lücke zu füllen unten)

std::vector<int> v { 1, 2, 3 }; 
auto it = v.find(2); 
if (it != v.end()) 
    v.erase(it); // v now contains 1, 3 

Also in der Theorie, nicht Sie nicht brauchen nullptr s setzen in Ihrem Vektor. Dies setzt voraus, dass Sie Ihre Anwendung so entworfen haben, dass in Ihrem Vektor keine bestimmte Populationsgröße erforderlich ist. Wenn dies der Fall ist, ist Vektor möglicherweise nicht der richtige Container. Betrachte std :: array.

Es gibt jedoch ein Problem mit Ihrem Renderable-Vektor: Der Vektor speichert Instanzen von Renderable. Die Elemente, die ich bin der Vektor sind genau die Größe eines Renderable. Wenn Sie also versuchen, eine abgeleitete Klasse zu speichern, z. B. Mesh, verlieren Sie die zusätzlichen Felder für abgeleitete Klassen.

Dies wird als Slicing bezeichnet.https://en.m.wikipedia.org/wiki/Object_slicing

Sie müssen Zeiger oder Verweise auf die Instanzen der Objekte speichern. Das hängt von der Lebensdauer und dem Besitz der Instanzen ab.

Wenn Ihr Vektor die Behebbaren besitzt, können Sie std::vector<std::unique_pre<Remediable>> verwenden.

Wenn Sie die Instanzen von Ihrem Anrufer erhalten, vielleicht std::shared_ptr.

+0

Danke für Ihre nützliche Antwort. So, wie man die Ausschnittprobleme löst? Zeiger? – PearlSek

1

Es gibt keine Notwendigkeit willkürlich „nichts“ Datensätze in einem std::vector zu setzen, ist dies nicht wie ein variabler Länge C-Stil-Array, wo Sie mit irgendeiner Art von Trennzeichen enden müssen . Lass es einfach leer.

In der allgemeinen Praxis möchten Sie vermeiden, NULL in Listen wie diese zu setzen, wo etwas über den Inhalt iterieren und diesen Zeiger erneut verweisen könnte, was einen Absturz verursacht.

+3

Vermeiden Sie auch 'NULL'. Verwende 'nullptr'. –

+0

'nullptr' ist in einigen älteren Versionen von C++ nicht definiert. –

+0

@MarkLakata Guter Punkt, aber egal wie Sie ihn angeben, "0" oder anders, ungültige Zeiger sollten nicht in dieser Liste sein. – tadman

0

Wenn RenderGroup eine Basisklasse ist und Ihr Children Vektor willkürliche Kinderklassen von RenderGroup speichert, dann ist dieser Ansatz "in Ordnung" (obwohl intelligente Zeiger wahrscheinlich bevorzugt würden).

Allerdings, wie Tadman erwähnt, wenn Sie Zeiger verwenden, um die Abwesenheit eines RenderGroup darzustellen, werden Sie wahrscheinlich stattdessen nur die Elemente im Vektor entfernen möchten, wenn sie nicht mehr benötigt werden.

0

Sehen Sie, wenn diese Struktur kann helfen:

struct RenderGroup { 
    std::map<Renderable, std::vector<RenderGroup*>> Renderables; 
} 

Liste des Kindes (RenderGroup) Objekte werden Render Objekt abgebildet.