Hi, I'm learning C++. I have a simple class named GameContext:

class GameContext {
        GameContext(World world);
        virtual ~GameContext();

To initialize a GameContext object, I need a World object.

  • Should the GameContext constructur take a pointer to a World object (World*), the address to a World object (&World) or a reference to a World object (World)?

  • What is the const keyword when used near a parameter? For example: GameContext(const World &world)


+3  A: 

Ideally, you should accept a const reference to World:

class GameContext {
        GameContext(const World& world);
        virtual ~GameContext();

First, so that no copying happens when passing the world. Second, const is keyword that means that you aren't going to change the passed parameter which is world in this case.

I agree. This is the way to go.
Thanks, then you call it like so: `World world; GameContext context(world);`?

Reference are safer than pointers and involve no copy. As for the const keyword read the answer to this question I made some time ago:


The const means that the method GameContext wont be able to modify the contents of the parameter world

+5  A: 

First, teminology: You're right that a World * would be a pointer to a World object. A World &, however, would be a reference to a World object. A World would be a copy of the World object, not a reference to it.

The const (used primarily with a pointer or reference, as in World const &world or World const *world) means that you're getting a reference/pointer to a const object -- in other words, you're not allowed to modify the original object to which it refers/points.

For small objects, you usually want to pass a copy. For large objects, you'll typically want to pass a const reference. There are exceptions to this, but that's a reasonable rule of thumb to use until you've learned enough more to know when to break the rules (so to speak).

Just based on the name, I'd guess your World object is probably large enough that you probably want to pass it by const reference, so your ctor should look like:

GameContext(World const &world);
Jerry Coffin
+1  A: 

Your terminology is way off.

In C++ terminology the terms pointer and address are synonyms (as far as we are talking about values). In order to take the pointer (or the address) you have to declare your parameter as World* world.

To take the reference, the parameter should be declared as World& world.

To take a copied value, the parameter should be declared as World world.

Which declaration you should use in each specific case depends on our intent. Assuming that World is a non-trivial object, the choice should normally be limited to either reference World& world or pointer World* world.

If you don't intend to modify the source World object in GameContext's constructor, a const should be added: const World& world or const World* world.

Finally, passing by pointer allows you to pass a "reserved" value - a null pointer - but at the same time prevents you from passing a pointer to a non-lvalue. If this does not matter much to you, then you should probably stick with a reference const World& world.

+1 Excellent answer.
The Real Diel
"In C++ terminology the terms pointer and address are synonyms" -> I disagree. Bytes are identified by addresses, whereas objects are identified by pointers. See [basic.compound] in the standard.
@FredOverflow: No, quite the opposite, most people tend to insist on the distiction, which doesn't really exist in reality. [intro.memory] is not trying to define the term "address". 5.3.1 proceeds to say "the address of an object of type “cv T” is “pointer to cv T,”. 13.4 is titled "Address of overloaded function", which would be totally meaningless under your interpretation of the term "address". Once again, in value context the terms "pointer" and "address" are exact synonyms in the standard language.
+1  A: 

World is not a reference to a World object - the compiler is making a copy of the structure and passing it through the stack. This is bad.

A pointer (World*) and a reference (World&) are very similar, they differ only in syntax (-> vs .) and scope (you can't assign a reference, so the member m_pWorld can't point to another World during the lifetime of your GameContext if you use a reference - but you can do that if you use a pointer). My advice is get a reference if you'll always use the same World (likely), or a pointer otherwise.

The const there tells the compiler you won't modify the object. When you get a reference to an object, you're working on the object, not a copy of it - so anything you modify in the method actually modifies the "outside" object. In your case, since you'll probably modify or otherwise operate on your World within GameContext, you probably want a non-const reference.

So you should do something like this

class GameContext 
    GameContext (World& pWorld) : m_pWorld(pWorld)

    virtual ~GameContext () { ... }

    void foo (int nParam)

    World& m_pWorld;

Should the GameContext constructur take a pointer to a World object (World*), the address to a World object (&World) or a reference to a World object (World)?

First of all, the "address to a World object" is the same thing as a pointer to a World object. A pointer is a type of variable that stores an object's address. If you pass an address, then the parameter that corresponds to the address you passed will be a pointer.

Whether you want to take a pointer or not depends on the semantics of the World class. If you take a value (and not a pointer), then you will receive a copy of the World object passed in. If something other than the GameContext object needs to perform operations on that same world object, then you will want to pass in and store a pointer. If this is not necessary, or if the World class operates internally such that all copies of a World object use a common set of data, then you can pass by value.

What is the const keyword when used near a parameter? For example: GameContext(const World &world)

const means "cannot be modified", just like it means anywhere else. A common idom in C++, as you have given in your example, is to take a constant reference instead of taking a value. When the parameter is an object (as opposed to a fundamental type like int or bool), this is more efficient than taking a value, since a copy is not made in this case. However the const prevents the function from modifying the referenced parameter, so to the caller, it does not matter than it is a reference.

Tyler McHenry