C++ Pointers

I’m going through some code that uses pointers to distribute objects into a function - a snippet of the code (example) is as follows:

display.draw(&controller) // Controller being a class

which links to the below function:

void Display::draw(Ball *ball)
{
  drawObject(1, ball->position);
}

I have a brief understanding of what pointers are, however, I’m failing to understand why they are used in this context? Why would we use pointers?


My current understanding is for space, as passing the address of the controller and then getting the value of the address of controller in the function would be the same as just passing controller (my understanding), why wouldn’t we just pass the class through and therefore access the position through controller.position.Would passing the class through be “too heavy” on memory?

Another idea I had was: as when we call the function display.draw() we don’t only pass through the class controller but other classes like &breakout.ball which also have a position that would need to be accessed and drew. Therefore allowing us to access the positions as doing controller.position would be hardcoded and wouldn’t allow us to change the class of [class].position - whereas if we do it with pointers we can say [pointer]->position and therefore point to the address of whatever class we want to access - therefore making it efficient and a good algorithm. Would my interpretation be correct?

I can supply the code if asked, please advise.

Thank you in advanced.

  • Jack

If your object is 32 bytes and you pass the object as a parameter to the function the entire object has to be copied onto the CPU stack to do the call so the function can work on a copy of the object.

If you pass a pointer or a reference then only the pointer or reference (2 bytes on AVR) needs to be put into registers (or the stack if you have too many parameters) to be passed along to the function.

So it’s a lot faster to pass a pointer or a reference.

References work like this:

void Display::draw(Ball &ball)
{
drawObject(1, ball.position);
}

display.draw(controller); // Controller being a class

References are hidden pointers to the original object that looks in the code like you’re accessing the object directly.

You can modify the original object through a pointer or a reference so if you don’t want that to happen it’s a good idea to mark the object type as const.

void Display::draw(const Ball &ball)

or

void Display::draw(const Ball *ball)
1 Like

There are various different reasons which depend on the circumstances involved…

  • Sometimes passing a pointer is indeed cheaper than passing a whole object.
    That depends on the size of a pointer compared to the size of an object,
    both of which can vary depending on the target CPU.
    (On the Arduboy pointers are 16 bits wide.)
  • Sometimes a pointer is used because the object pointed to by the pointer needs to be modified.
  • Sometimes you use a pointer when you want to make use of virtual functions and inheritance.
  • Sometimes a pointer is the only option.
    This is the case with the ‘progmem’ reading functions on AVR (the architecture of the Arduboy’s CPU).

It’s hard to comment on any particular code without being able to see all of it,
but in this case I’d guess Ball is probably quite a large class and passing a pointer is cheaper.

(Personally I don’t think the use of drawObject here makes much sense.)

You appear to be getting ‘class’ mixed up with ‘object’.
A class is a blueprint for an object.
An object is the actual bundle of data manipulated by the CPU.

display.draw(&controller)

Ball is a class, controller is an object.
Display is a class, display is an object.

No, it wouldn’t be the same.

Consider this:

class ClassA
{
	uint8_t data[16];
};

void functionA(ClassA a)
{
}

void functionB(ClassA * a)
{
}

void test()
{
	ClassA objectA;
	functionA(objectA);
	functionB(&objectA);
}

Using functionA requires passing an object (an instance of ClassA) to the function.
The size of an object of type ClassA is 16 bytes.

Using functionB requires passing a pointer to an object of type ClassA.
The size of a pointer varies between system, but practically all systems have a pointer that is smaller than 16 bytes,
thus passing a pointer would probably be cheaper.

I don’t think I quite understood what you were trying to say.
I have (at least) two different interpretations of what you were trying to say.
The answer for one interpretation is ‘no’,
the answer for the other interpretation is ‘yes, but not in this case’.

2 Likes

Hi Pharap,

Thank you so much for your detailed reply, I now understand about pointers and why we use them! Brilliant explanation.

Best regards,

Jack Daly

1 Like

If you have any more questions or would like any help with anything, feel free to ask.


As @rv6502 mentioned references, I’d like to point out that in C++ references are typically preferred to pointers because they can’t be null (nullptr) and can’t be reassigned, so they are less ‘dangerous’.

However there are situations where you have to use a pointer because they can do things references can’t do (e.g. be nullptr, be reassigned).

1 Like

For completeness: They cannot legally be null according to the c++ standard but in practice they can when null pointers are dereferenced to initialise them which is a big gotcha.

Just a heads up for c++ newbies.

And null pointers / references don’t instantly stop the program on AVR because there’s no MMU and address zero is a valid hardware address ( maps to register 0 ) so funky stuff can happen.

I’ve done that. It was not fun trying to figure out what went wrong. Most times the running program will just freeze, but in my case things got a little dicey and it just started going on the fritz. Nothing that would potentially cause physical damage to the hardware just nothing I expected it to be doing.

1 Like

That can only happen if you’re mixing references and pointers though,
which from my experience is a relatively uncommon thing to be doing anyway.

Ultimately the problem comes from dereferencing pointers, not from using references.
You’d have the same problem assigning to a non-reference type,
hence it’s a caveat of pointers, not a caveat of references.

Either way, null pointer checks are imperative if you’re going to be using pointers,
which is one of the reasons why references should be preferred.