PearlSek
PearlSek

Reputation: 100

C++ : Null pointers and structs

If I want to make a struct for representing an item to render on the screen, and contains:

  1. A list of natives "renderables" (meshes, triangles, etc)
  2. A pointer to others sub-structures

Does this:

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

What is the best way to do this? And if I have no sub-structures, can I just put a null pointer in the vector ?

Edit : Bad tags

Upvotes: 1

Views: 622

Answers (4)

kfsone
kfsone

Reputation: 24249

A std::vector is not fixed size, so if there are no elements in it, size will return 0 and empty will return true.

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

You can also remove elements (the vector moves all the followingv elements down to fill the gap)

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

So, in theory, no you don't need to put nullptrs in your vector. This assumes you've designed your application in a way that doesn't require a certain population size in your vector; if so, vector might not be the right container. Consider std::array.

There is a problem with your renderables vector, though: the vector stores instances of Renderable. The elements I'm the vector are exactly the size of a Renderable. So if you try and store a derived class, e.g Mesh, you will lose the derived classes extra fields.

This is called slicing. https://en.m.wikipedia.org/wiki/Object_slicing

You'll need to store pointers or references to the instances of the objects. Which depends on lifetime and ownership of the instances.

If your vector owns the remediables, you could use std::vector<std::unique_pre<Remediable>>.

If you are being given the instances from your caller, perhaps std::shared_ptr.

Upvotes: 1

Matta
Matta

Reputation: 43

See if this structure can help:

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

List of child (RenderGroup) objects are mapped to Renderable object.

Upvotes: 0

Altainia
Altainia

Reputation: 1597

If RenderGroup is a base class and your Children vector is storing arbitrary children classes of RenderGroup then this approach is "fine" (though smart pointers would probably be preferred).

However, as tadman mentioned, if you're using pointers to represent the absense of a RenderGroup, you'll probably want to instead just remove the items in the vector when they are no longer needed.

Upvotes: 0

tadman
tadman

Reputation: 211560

There's no need to put arbitrary "nothing" records in a std::vector, this isn't like a variable-length C-style array where you must terminate with some kind of delimiter. Just leave it empty.

In general practice you want to avoid putting NULL into lists like this where something might iterate over the contents and re-reference that pointer, causing a crash.

Upvotes: 1

Related Questions