🎉 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, 2 months ago
Common Explosion Scenario:
void SomeFunction(DataType *& ptr){  DataType * temp = new DataType;  // initialize temp  ptr = temp;  delete temp; // ptr now points at invalid memory block}...DataType * obj;SomeFunction(obj);obj->Some_DataType_Member; // BOOM!obj->SomeOther_DataType_Member(); // BOOM!

In both of the two final statements above, the attempt to dereference ptr, which occurs at runtime so the compiler can't help you detect this, causes an access violation. This is why ownership semantics are so important in C++.

As an interesting aside, imagine if you had a global pointer, and then a piece of code somewhere deleted the memory it pointed at. The next usage would generate an access violation, and it could be fairly difficult to track down where the error was introduced. This is why globals are often frowned on in C++ programming: because they make debug determination of object state a hit-and-miss process.
Advertisement
Quote: Original post by RinusMaximus
I'm confused about this. Does this mean that in the following piece of code the delete on pTemp will free the memory allocated for pTemp? Eventhough pNew has a reference to the allocated memory?

DataType* pTemp = new DataType;DataType* pNew = pTemp;delete pTemp;

Absolutely correct. C++ does not make sure that you discard all pointers to memory before deallocating it. After the code above is run, pNew is pointing at an invalid space in memory. Any attempt to use pNew could result in corrupted memory or (if you're lucky) a complete crash.

This means it's vitally important to know what function or class "owns" the memory allocated with new, so you know to delete it exactly once. If I must use a function (or class method) to create an object with new and return a pointer to it, I create an analogous function (or class method) to release that memory.

[OPINION]
In real life, though, I rarely use functions to create objects with new and return pointers. The idea of the construct is to create a new object on the heap and then set it up properly before returning it. But that's what constructors & destructors are for! I'd say that the vast majority of my new and delete operators are operating on class member variables inside of constructors and destructors.

General rule: If you find yourself doing a lot of work on the [edit]heap, wrap that work up in a class, and do 'new' in the constructor and 'delete' in the destructor.
[/OPINION]

[Edited by - BeanDog on July 24, 2006 12:23:30 PM]
Quote: General rule: If you find yourself doing a lot of work on the stack, wrap that work up in a class, and do 'new' in the constructor and 'delete' in the destructor.


Why do you say this? At our company the general rule is to always use the stack and avoid the heap all together. I don't think I've used new in a very long time.

-= Dave

Quote: Original post by ph33r
Quote: General rule: If you find yourself doing a lot of work on the stack, wrap that work up in a class, and do 'new' in the constructor and 'delete' in the destructor.


Why do you say this? At our company the general rule is to always use the stack and avoid the heap all together. I don't think I've used new in a very long time.

-= Dave

Thanks, I mistyped. I meant 'heap'. The idea is that some algorithms really require large chunks of memory, and it's better to use a class to represent that chunk of memory and the algorithm than to allocate and deallocate the memory outside a class.
Quote: In real life, though, I rarely use functions to create objects with new and return pointers. The idea of the construct is to create a new object on the heap and then set it up properly before returning it. But that's what constructors & destructors are for! I'd say that the vast majority of my new and delete operators are operating on class member variables inside of constructors and destructors.


This is probably too advanced for this point, but a chapter on pointers shouldn't be taught without atleast mentioning smart pointers.
As an adendum to that opinion; this is much of the motivation behind std::auto_ptr. If you store the result of your 'creation' function in an auto_ptr, you needn't worry about deleting it. Auto_ptr will take care of that for you. You must still be careful, however. Copying an auto_ptr destroys the source instance, which makes it difficult to use for more than automatic clean up.
A reference counted smart pointer (such as boost::shared_ptr or boost::intrusive_ptr) is often the better choice.
In general, you should avoid manual memory managment. Let a smart pointer do it for you!
Are smart pointers going to be handled somewhere later in the course? If not it might be nice to do some exercises with smart pointers this week (review week).

I have been reading some other material too and it seems like most people use the boost library for smart pointers. Does anyone have links to articles that explain the smart pointers?
Chapter 7 of 'Modern C++ Design'
Quote: Original post by RinusMaximus
Are smart pointers going to be handled somewhere later in the course? If not it might be nice to do some exercises with smart pointers this week (review week).

I have been reading some other material too and it seems like most people use the boost library for smart pointers. Does anyone have links to articles that explain the smart pointers?


Smart pointers are nice BUT you won't be able to use them correctly if you don't fully understand the notion of pointers. Once you are experienced with C++ and the way the memory is managed, you'll find plenty of time to use smart pointers. For the time beeing, I really suggest you to stick to the normal, C++ pointers. Moreover, they use concepts that haven't been introduced yet (templates and so on) thus they might be confusing.

Regards,
Greetings All!

It's once again QUIZ TIME!!! That's right, listed below are a set of quiz questions to help you test your knowledge and understanding of the material contained in chapters 8.

In addition to the questions and exercises below, make sure that as you're reading the book you enter the examples into your compiler, build the program, and run the executable. I know this is a time consuming process, but the repeat use of keywords, syntax, and semantics will help ingrain the information into your long-term memory. My advice is to create a simple "driver" project with a function main. As you read, enter the examples into function main, test it, and then erase it for use again in the next example.

PLEASE DO NOT POST THE ANSWERS TO THESE QUESTIONS OR EXERCISES. If you are unable to answer these questions, please ask for assistance, but DO NOT POST THE ANSWERS. Any question which is not marked with [Extra Credit] can be answered by reading your textbook. Questions which are marked [Extra Credit] either have been answered in the thread previously, or can be answered by doing a bit of research.

I will create an answer thread for these questions immediately, so that people will have a chance to get the answers more quickly.

Chapter 8 Quiz

1. What is a pointer?
2. What is a variables address?
3. What operator do you use to get the address of a variable?
4. How would you declare a variable which is a pointer to a character?
5. How would you assign the address of a character to a character pointer variable?
6. What is it called when you use a pointer variable to obtain the data stored at the address it holds?
7. Why must we tell the compiler what type a pointer is, if all pointers are the same size?
8. What operator do you use to indirectly get the data stored at the address held by a pointer?
9. If you allocate memory on the heap while in a function, is the data available after the function returns?
10. Why are destructors so critical?
11. How would you allocate a ‘char’ on the heap and store the address so as to access the data later?
12. How would you set the value of the data in question 11 to the character ‘c’.
13. What keyword do you use to return the memory you’ve allocated back to the operating system?
14. What is it called when you have unused memory which is not freed until the progam ends either because the program author failed to release the memory when finished, or the address to the memory was lost, making it impossible to free.
15. In addition to allocating memory for an object, what function is always called on an object after it is created with ‘new’?
16. What function is called when you use the delete operator on an object, just before the memory is freed?
17. What is the long-hand way of accessing methods or data on an object indirectly via a pointer? Show an example to illustrate.
18. What is the short-hand way of doing the same thing as in question 17.
19. What is ‘this’?
20. What is a dangling pointer?
21. What’s different between “const int*”, “int * const”, and “const int * const”? How are these read?
22. If you have a pointer to a constant object, which member functions can be called on that object?

Good luck!
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
I see that objects can be created on the free store, as can member data but I'm confused regarding objects being on the free store.

Suppose I have a class Cat, and create two objects, pFrisky and Benny, along with two data members, itsAge and itsWeight. If pFrisky is created using new, it's on the free store but if Benny is created without new, it's created on the stack (I think that is this correct). Further, if itsAge is created "normally" (without new), it's on the stack and itsWeight, created with new, is on the free store (in listing 8.7, why doesn't the book suggest that itsAge and itsWeight start with lower case p as per the convention?).

There are four permutations - where are they, on the stack or free store?

pFrisky.itsAge (is this meaningful?)
pFrisky.itsWeight (is this meaningful?)
Benny.itsAge
Benny.itsWeight

Is this possible or would an error be generated? 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? What are the reasons?

This topic is closed to new replies.

Advertisement