🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

C++ Workshop - Pointers (Ch. 8)

Started by
87 comments, last by mihaimoldovan 12 years, 3 months ago
The memory footprint of the object; that is, how much memory you need to store the object; includes space for all member variables. You don't need to create members seperatly, unless they are themselves pointers. With your example, when you do 'new Cat()', you aquire 'sizeof(Cat)' memory. The size of Cat is the sum of the size of all members, plus additional bits the compiler can add such as a virtual function table and base classes and other errata.

So, in short, yes. The members are created right there with it when you new it.

Quote: in listing 8.7, why doesn't the book suggest that itsAge and itsWeight start with lower case p as per the convention?
Because itsAge and itsWeight are not pointers. The book is using p to denote pointers, not where in memory the object is located. The members aren't pointers. Their lifetime is controlled by the class, just as if they were on the stack.

Quote: pFrisky.itsAge (is this meaningful?)
No; but pFrisky->itsAge is.

Quote: Is it good practice to mix like this or would it be better to have all objects and member data on either the stack or free store?
Don't think of an object as just a collection of members. You don't allocate members; you allocate whole classes. If you have a pointer member, and you allocate memory for it to point to, don't mistake that for allocating a member. The pointer itself is the member, the memory it points to isn't actually part of the class.
Advertisement
Thank you.

I think my original confusion arose when it said in the book that I can create an object on the free store (the example in 8.5 is SimpleCat * pRags = new SimpleCat). What went through my head at that stage (and still does), is that neither Frisky nor Benny can actually hold any data, but Frisky.itsAge and Benny.itsWeight can. As Frisky and Benny can't hold data, why should I be able to point at them? I can understand why I should be able to use a pointer to store the memory addresses for Frisky.itsAge and Benny.itsWeight.
Quote: Original post by Deyja
Because itsAge and itsWeight are not pointers. The book is using p to denote pointers, not where in memory the object is located. The members aren't pointers.


I've been looking at this again. In lines 18 and 19 of listing 8.7, it states "int * itsAge;" and "int * itsWeight;". In addition, in the analysis section at the bottom of page 242, it states that " ... SimpleCat is declared to have two member variables - both of which are pointers to integers - on lines 18 and 19."

The book follows the convention of prefixing pointers with lower case p, so why not on this occasion? Is there a good reason for this deviation, or does this simply serve to confuse absolute C++ newbies like me?
Quote: is that neither Frisky nor Benny can actually hold any data, but Frisky.itsAge and Benny.itsWeight can. As Frisky and Benny can't hold data, why should I be able to point at them?

'Cat' is a whole new type that is a conglomerate of itsAge and itsWeight. It's value is the combination of itsAge and itsWeight.

Quote: The book follows the convention of prefixing pointers with lower case p, so why not on this occasion? Is there a good reason for this deviation, or does this simply serve to confuse absolute C++ newbies like me?

Ah, I don't have the actual book. Sorry about that. Perhaps he just didn't want it to read 'pitsAge'? It's just a naming convention (And one I personally despise) Don't worry about it.
Thank you for your time (and patience!).

I'm sure that this will all crystallise in due course. I'm looking forward to getting through to chapter 21 because the first thing I intend doing is reading the book again, in conjunction with the comments in each of these chapter threads. By going through everything again with "knowing eyes", I hope that I'll learn even more.
Condor,

Sorry I haven’t been able to respond as much lately. Having a 1 month old baby eats up a good amount of my time. =) But let me see if I can help re-explain what Deyja said, just so you get the info a second time, perhaps explained in a slightly different fashion.

First, don’t let the naming convention confuse you. How he chose to name the variables has nothing to do with the functionality of those variables. And as we've seen from this discussion, the important thing is to remain consistent. He suggests using 'p' at the beginning of a variable name to denote a 'pointer', but then clearly forgets to use it when working with member variables of standard types. Either he "forgot" to use it or his own coding style does not use the 'p' on either member variables or pointers to standard data types. Those are the only logical reasons he might have for NOT using the 'p'. I, however, would have continued to use the 'p' for consistency.

As to what I suspect is your second question. When you define a class, you're describing a new data type which is a collection of data and behaviors. The data and behaviors cannot be separated from each other or from the class. Whenever you declare an instance of a class - that is, an object - the compiler allocates enough memory to hold the entire object, as well as some additional space necessary for the function table. This is true whether you allocate the object on the stack, or the heap.

Now, consider the following class:
class MyClass{    int  m_MyInteger;    char m_MyCharacter;    char* m_pMyPointer;}

Whenever I create an instance of the above class, I will allocate roughly 9 bytes of memory. Why 9? Well, because the integer takes 4, the character takes 1, and the pointer to a character takes 4. Add them up, and that's 9 bytes of data to hold this class.

But wait? should the char* be 1 byte...after all a character is 1 byte? NO! m_pMyPointer is not a character. Its a pointer. A pointer must be large enough to hold an address - and on most modern machines, that's 4 bytes. The important thing to remember is that all of the above variables will be allocated...whether on the stack or on the heap.

Now...the 9 byte allocation is the same whether I create the above object on the stack or on the heap. So what's the difference then? Well, there is none. What the book was trying to say is simply that it's possible to have pointer variables inside of classes...in this case, m_pMyPointer is a variable which holds an address...a pointer, but in order for you to access it, you must also allocate the memory which it points to. By default it holds an invalid address in it, or if you're a good programmer you've initialized it to the value 0 or NULL. So just as you allocated memory to store the object, you must allocate memory to store the data pointed at by m_pMyPointer.

But wait...didn’t I allocate the memory for m_pMyPointer when I allocated the object? Yes...and no. What you allocated was the memory necessary to hold the address of the data. You did not allocate the space in memory where the data is actually going to be located. Remember, a pointer is just a variable which holds an address. But until you allocate some memory and store the address of that new memory in the pointer...its useless.

Most often pointer variables within classes are allocated in the constructor, as you can see in the book on page 242 lines 24-25. The equivalent here would be:

m_pMyPointer = new char;

Now m_pMyPointer holds a valid address and I can access it without worry. So keep in mind, when working with pointers you've got 2 components. The memory for the pointer, and the memory the pointer "points to". Putting pointers in classes DOES allocate the memory for the pointer. Putting pointers in classes does NOT allocate the memory the pointer points to...you must do that yourself in the constructor or in another function.

Cheers!
Jeromy Walsh
Sr. Tools & Engine Programmer | Software Engineer
Microsoft Windows Phone Team
Chronicles of Elyria (An In-development MMORPG)
GameDevelopedia.com - Blog & Tutorials
GDNet Mentoring: XNA Workshop | C# Workshop | C++ Workshop
"The question is not how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" - Il Duche, Boondock Saints
That's great - thank you.

It's good to see you back and we all appreciate that you have to divide your time now into more segments. I don't have any family but am sure that it consumes a lot of your energy.
Quote: Original post by Oluseyi
Common Explosion Scenario:
void SomeFunction(DataType *& ptr)



Could someone please explain the parameter passed , its the first time i have come across it :|.

"I think there is a world market for maybe five computers." -- Thomas Watson, Chairman of IBM, 1943
Quote: Original post by Nokturnal
Quote: Original post by Oluseyi
Common Explosion Scenario:
void SomeFunction(DataType *& ptr)



Could someone please explain the parameter passed , its the first time i have come across it :|.


Its passing a DataType pointer (DataType *) by reference ( the & ). It seems references haven't been covered just yet so I won't go into detail, but they allow some of the behaviour of pointers with a simpler syntax but important restrictions.

I'm sure it will be covered in the next few chapters anyway.
Fair enough , thanks!
"I think there is a world market for maybe five computers." -- Thomas Watson, Chairman of IBM, 1943

This topic is closed to new replies.

Advertisement