Jump to content
  • Advertisement
Sign in to follow this  
Klutzershy

When to point to an object vs. hold it directly in a variable

This topic is 2513 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I know that there are two ways to "store" an object in C++:


// using a variable
Car myCar;
myCar.drive();

// using a pointer
Car *myCarPointer = new Car();
myCarPointer->drive();
delete myCarPointer;


The second method is the way you would do it in C# or Java (minus the manual deletion), but both are valid in C++. The book I use (C++ Programming in Easy Steps) doesn't outline the difference other than that it looks like you can do something like this with a derived class:


BaseClass *object = new DerivedClass();


In the context of a game, when would you want to use one over the other?

Share this post


Link to post
Share on other sites
Advertisement
Several Reasons:

1) Object lifetime
With Car myCar the object lives until it falls out of scope. myCar is allocated on the stack which may be faster if not as fast than a allocation from the heap. If the object needs to live longer than the scope it belongs to, then it must be allocated on the heap, where the object must be destroyed manually with delete.

2) Which-object
A pointer or reference can describe "which object". A pointer must be used to retreive something from the heap, though a pointer doesn't necessarily need to point to a dynamically allocated object:

Car hisCar; // stack
Car* myCar = new Car; // heap

Car* whichCar = (rand() & 0x08) ? &hisCar : myCar; // pointer on stack, may point to stack or heap
Car& anotherCar = (rand() & 0x08) ? hisCar : *myCar; // anotherCar "is" either "hisCar" or "myCar"

whichCar->drive();
anotherCar.drive();

whichCar = 0; // or NULL or nullptr

delete myCar;


3) Interfaces
In the case of games, one can use inheritance to generalize a lot of game objects:


class Entity {
public:
virtual ~Entity() { }
virtual void update() = 0;
virtual void render() = 0;
};

class Player : public Entity {
public:
void update() {
cout << "Player::update()\n";
}
void render() {
cout << "Player::render()\n";
}
};
class Monster : public Entity {
public:
void update() {
cout << "Monster::update()\n";
}
void render() {
cout << "Monster::render()\n";
}
};

int main() {
Player thePlayer;
Monster aMonster;
Monster* others[2] = { new Monster, new Monster };

Entity* ents[4] = {
&thePlayer, aMonster, others[0], others[1]
};

for ( int i = 0; i < 4; ++i ) {
ents->update();
ents->render();
}

delete others[0];
delete others[1];
}


Hope this helps.

Additional reading:
http://www.parashift.com/c++-faq-lite/references.html
http://www.parashift.com/c++-faq-lite/basics-of-inheritance.html
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html

Share this post


Link to post
Share on other sites

I know that there are two ways to "store" an object in C++:


// using a variable
Car myCar;
myCar.drive();

// using a pointer
Car *myCarPointer = new Car();
myCarPointer->drive();
delete myCarPointer;


The second method is the way you would do it in C# or Java (minus the manual deletion), but both are valid in C++. The book I use (C++ Programming in Easy Steps) doesn't outline the difference other than that it looks like you can do something like this with a derived class:


BaseClass *object = new DerivedClass();


In the context of a game, when would you want to use one over the other?


There are two big differences:
1) Things you allocate with new will be allocated on the heap (normally) (things created the first way ends up on the stack), the stack is normally faster but stack space is limited.
2) Multiple pointers can point to the same object (So if you are going to share one object between multiple other objects then pointers are good, allthough you could still allocate the object in question on the stack).

a few generic rules you can follow if you want:
* allocate small or short lived objects on the stack.
* allocate large objects on the heap
* don't use raw pointers (unique_ptr and shared_ptr are much better option in most cases),

so rather than
Class *obj = new Class()
....
delete obj;

you do

shared_ptr<Class> obj(new Class())
shared_ptr<Class> obj2(obj);
code
no need to delete, its handled automatically and if you have multiple shared pointers to the same object(i made 2 in the example) the deletion will happen when all shared pointer have gone out of scope. unique_ptr works in the same way except it cannot be copied (like i did with the shared pointer) and thus doesn't have to count references (as you can only have one unique_ptr to each object that object gets deleted as soon as the unique_ptr goes out of scope)

Share this post


Link to post
Share on other sites

a few generic rules you can follow if you want:


[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

* allocate small or short lived objects on the stack.[/font]


[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

* allocate large objects on the heap[/font]


[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

* don't use raw pointers (unique_ptr and shared_ptr are much better option in most cases),[/quote][/font]


[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

Perfect, thanks![/font]



If I was to make a vector of Entities, I would do something like this, right?


// create
vector<Entity> *entities;
entities->push_back(new Player());

// update
for(int i = 0; i < entities.size(); i++)
entities->update();

// delete
int s = entities.size(); //
for(int i = 0; i < s; i++) // redundant?
delete entities; //
delete entities;

Share this post


Link to post
Share on other sites
No. First, entities probably shouldn't be a pointer. std::vector is not a large data type, and so it should be on the stack (unless you have a really, really good reason for putting it on the heap). You've got a few syntax errors there since entities is a pointer, but you're treating it like it's not a pointer.

Second of all, entities doesn't hold pointers. It holds actual Entity objects (i.e. the full object, not a pointer to an Entity object). So you shouldn't be adding to with new Player(), nor should you have to use the -> operator, nor should you have to delete the elements in the vector.

You probably meant something more like this:

vector<Entity*> entities;
entities.push_back(new Player());

for (int i = 0; i < entities.size(); i++)
entities->update();

for (int i = 0; i < entities.size(); i++) // Note: calling delete entities doesn't change the size of entities
delete entities;


Note, however, that it is really, really, *really* discouraged to use raw pointers within a vector. If entities goes out of scope or gets its destructor called when an exception is thrown, the memory of the Entity objects is never freed, and you've got a memory leak. As SimonForsman said, using some kind of smart pointer is a much more preferred solution. If you were doing that, you could do something like this:


vector<std::shared_ptr<Entity>> entities; // std::shared_ptr or boost::shared_ptr, depending on if you're using C++11 or boost
entities.push_back(new Player());

for (int i = 0; i < entities.size(); i++)
entities->update();

// Look, no cleanup! It all gets handled automagically

Share this post


Link to post
Share on other sites

In the context of a game, when would you want to use one over the other?

Not to answer your question, but because you mentioned "in the context of a game", I suggest you consider about cpu cache optimization (google if you are not familiar with it) in your memory management strategy.
cpu cache may influence how you manage your memory, and the performance of your game.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!