Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


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


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
5 replies to this topic

#1 Boreal Games   Members   -  Reputation: 849

Like
0Likes
Like

Posted 23 January 2012 - 02:53 PM

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?

Sponsor:

#2 fastcall22   Crossbones+   -  Reputation: 4456

Like
2Likes
Like

Posted 23 January 2012 - 03:10 PM

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[i]->update();
        ents[i]->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
c3RhdGljIGNoYXIgeW91cl9tb21bMVVMTCA8PCA2NF07CnNwcmludGYoeW91cl9tb20sICJpcyBmYXQiKTs=

#3 SimonForsman   Crossbones+   -  Reputation: 6293

Like
3Likes
Like

Posted 23 January 2012 - 03:20 PM

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)
I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

#4 Boreal Games   Members   -  Reputation: 849

Like
0Likes
Like

Posted 23 January 2012 - 07:02 PM

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),

Perfect, thanks!


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[i]->update();

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


#5 Cornstalks   Crossbones+   -  Reputation: 6991

Like
0Likes
Like

Posted 23 January 2012 - 07:55 PM

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[i]->update();

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

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[i]->update();

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

[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#6 wqking   Members   -  Reputation: 756

Like
-1Likes
Like

Posted 23 January 2012 - 08:03 PM

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.

http://www.cpgf.org/
cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.
v1.5.5 was released. Now supports tween and timeline for ease animation.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS