• Advertisement
Sign in to follow this  

C++ avoiding pointers

This topic is 1272 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

 

I am working on a game using SDL. I was pointers to some 2d primitives, however probably to bad management there were some memory leaks. I switched to use references and not allocate dynamic memory. I believe the problems were due to not following the rule of 3 (not declaring explicitly the assignment operator).

 

So, my questions is: should I try to avoid dynamic memory allocation. For example, I know that some object is needed in the scope of a function or that it should last for a very very brief period where a few functions have to work on it. Should I in this case pass by reference or by pointer to the object?

 

What do you think?

 

To me, it seems that dynamic memory allocation is helpful only when one has to create an array where the size of the array is not known.

 

I would be grateful if you give some hints and point out when they would be definitely necessary to be used.

Share this post


Link to post
Share on other sites
Advertisement

Don't avoid pointers out of fear; if you're purposely avoiding them then maybe C++ isn't for you, you might be better off using another language. You can make some pretty intense gfx games with C# (if you're writing for the Windows eco-system.) As already stated there are a number of rules-of-thumb, some tried and true patterns, and some really great new support in C++0x that make pointer management pretty easy.

 

Another thing you can do; when I was starting out with C I sat own with my compiler (and GCC or CLang is really nice for this, you can just install cywin and the gcc toolchain if you're not willing to stray from windows) and worked through some example pointer patterns until I got a fairly deep understanding of how they work. It didn't take long either.

 

If you want to be a proficient programmer with graphics you should invest the time it takes to be comfortable with pointers. Either that or just write tic-tac-toe games with other languages. Smart phone developers seem to do pretty well.

 

Share this post


Link to post
Share on other sites

Smart pointers, smart pointers, smart pointers.

 

The whole idea of a smart pointer is that they effectively allow you to hoist dynamic, non-deterministic memory usage into the realm of static, deterministic memory usage where you can effectively treat them as value-types.

 

Today, you basically don't have to think about the Rule of 5 or rule of 3 -- provided that use an appropriate smart pointer whenever a heap object is owned, and you only use raw pointers when no ownership is implied. Which kind of pointer you use is easy once you understand what each kind of pointer does -- your entire decision-making process can be expressed through a flow-chart that fits on a postcard. The only part that's a bit tricky is learning to recognize where weak_ptr fits in, but the entire landscape is a whole lot smaller than what you need to know to implement correct memory management patterns using new/delete directly.

Share this post


Link to post
Share on other sites

>> Smart pointers, smart pointers, smart pointers.

Sure, but then there is the philosphy that says smart pointers are over-used. One point; it's easy to avoid too much dynamic allocation through efficient design. Also, interfaces shouldn't return a smart pointer. You don't want to expose your memory management strategy to the outside to prevent the clients from making any assumption. That way lies madness. Smart pointers also step on performance, increase object contention, I could go on. Smart pointers aren't bad; they're like anything, use 'em too much and you can end up in "Bad Design Land". The ways are many, the exits few.

Edited by interval

Share this post


Link to post
Share on other sites
Also - I should mention that "avoiding pointers" is not something you can realistically do. For example, are you opening a file on disk to read a model or texture? That's a "pointer" to a non-memory resource you have to clean up at some point. Did you open a window to render to? That's also a "pointer" to a non-memory resource.

Ironically, languages without memory pointers still have these non-memory pointers somewhere and rarely have convenient mechanisms for dealing with them (see .NET's IDisposable pattern compared to C++'s deterministic destructors).

Resource management is a fact of life in programming, no matter what language you're using. So might as well learn it early smile.png

Share this post


Link to post
Share on other sites

You should be avoiding pointers if at all possible.  You'll know when the time comes to use them, because in those circumstances it won't be possible to do what needs to be done.  In practice, most objects are temporaries, and unless the temporary in question is ungodly large, you'll be allocating it on the stack, which means no pointers.

 

Dynamic memory allocation is useful (and required) in the following instances:

  1. Your object is too large for the stack.
  2. Your object needs to persist outside the lifetime of the allocating scope (i.e. past the '}')
  3. You want to share your object across multiple threads (usually a bad idea).
  4. You have some kind of stupid control flow requiring it, like throwing gotos around everywhere (really just a specialization of #2).

 

#2 is pretty much unavoidable in any reasonably complex program, but what's important is to recognize when it's necessary.

Share this post


Link to post
Share on other sites

Don't avoid pointers out of fear; if you're purposely avoiding them then maybe C++ isn't for you, you might be better off using another language. You can make some pretty intense gfx games with C# (if you're writing for the Windows eco-system.) As already stated there are a number of rules-of-thumb, some tried and true patterns, and some really great new support in C++0x that make pointer management pretty easy.

 

Another thing you can do; when I was starting out with C I sat own with my compiler (and GCC or CLang is really nice for this, you can just install cywin and the gcc toolchain if you're not willing to stray from windows) and worked through some example pointer patterns until I got a fairly deep understanding of how they work. It didn't take long either.

 

If you want to be a proficient programmer with graphics you should invest the time it takes to be comfortable with pointers. Either that or just write tic-tac-toe games with other languages. Smart phone developers seem to do pretty well.

 

Since programming in C and later moving to C++ professionally for 15 years (university and learning by myself before that), and understanding all the nuances of pointers, even I on rare occasions forget to delete/free() some pointer.  And that always causes some problem, often hard to track down ones.

 

Using smart pointers can remove that small bug that all humans are prone to create.So, it isn't about being "afraid" of pointers, it's just common sense.

 

Heck, I'm a really good driver, why would I need an air bag in my car?  I don't ever make a mistake while driving....

Share this post


Link to post
Share on other sites
So, it isn't about being "afraid" of pointers...

Isn't that something you should ask the OP about? Sounds to that's exactly what he was talking about.

 

Dynamic memory allocation is useful (and required) in the following instances:
  1. Your object is too large for the stack.
  2. Your object needs to persist outside the lifetime of the allocating scope (i.e. past the '}')
  3. You want to share your object across multiple threads (usually a bad idea).
  4. You have some kind of stupid control flow requiring it, like throwing gotos around everywhere (really just a specialization of #2).

 

#2 is pretty much unavoidable in any reasonably complex program, but what's important is to recognize when it's necessary.

 

Um, 3 is often unavoidable in any useful program, and very common. that's why locks and mutexes are for. You don't share access so much as control access serially to one or more threads.

Share this post


Link to post
Share on other sites


The real proper use of these are all based on _lifetimes_. Who is responsible for creating the object? Who is responsible for destroying? Are users of the object just borrowing it for a while or do they need to take over responsibility of the lifetime? If they're just borrowing the object, how long do they need to borrow it for?
Quoted for emphasis.

I honestly find given proper design thinking about ownerships and lifetimes beats smart pointers at large.

Share this post


Link to post
Share on other sites

 

There is nothing wrong with using dynamic memory. In fact, for any suitably non-trivial application you will find it impossible to NOT have dynamic memory allocation.
 
If you're doing this in C++ then you should be using modern C++ methodologies, such as smart pointers.
 
Additionally, when implementing your own classes that contain raw pointers you should always be sure to implement the rule of three at the minimum, rule of five at best.


While understanding and following the Rule of Three/Five is important, I would suggest striving for the Rule of Zero. (Which is basically a variation on the single responsibility principle)

 

EXACTLYYYYY finally one man on earth understands programming. damn. why is it so hard to make people forget about those damned rule of 3/5 ?

Share this post


Link to post
Share on other sites

There is nothing wrong with using dynamic memory. In fact, for any suitably non-trivial application you will find it impossible to NOT have dynamic memory allocation.
 
If you're doing this in C++ then you should be using modern C++ methodologies, such as smart pointers.
 
Additionally, when implementing your own classes that contain raw pointers you should always be sure to implement the rule of three at the minimum, rule of five at best.


While understanding and following the Rule of Three/Five is important, I would suggest striving for the Rule of Zero. (Which is basically a variation on the single responsibility principle)

EXACTLYYYYY finally one man on earth understands programming. damn. why is it so hard to make people forget about those damned rule of 3/5 ?


Because it's still important to know, especially if (when) you write your own resource management classes.

Share this post


Link to post
Share on other sites

EXACTLYYYYY finally one man on earth understands programming. damn. why is it so hard to make people forget about those damned rule of 3/5 ?


Not knowing the rule of 3/5 is like not knowing for loops. You have a giant gaping hole in your knowledge just waiting to come along and bite you on the ass.

There are a great many situations where the "rule of zero" will not work conveniently without you implementing the appropriate containers or proxies (which need to obey the rule of 3/5, by the way) in order to have your "rule of zero." Two examples where you need non-trivial handling of objects where the standard library is lacking convenient containers: handle duplication and COM with proper reference handling, unlike most DirectX code. Edited by Washu

Share this post


Link to post
Share on other sites

 

EXACTLYYYYY finally one man on earth understands programming. damn. why is it so hard to make people forget about those damned rule of 3/5 ?


Not knowing the rule of 3/5 is like not knowing for loops. You have a giant gaping hole in your knowledge just waiting to come along and bite you on the ass.

There are a great many situations where the "rule of zero" will not work conveniently without you implementing the appropriate containers or proxies (which need to obey the rule of 3/5, by the way) in order to have your "rule of zero." Two examples where you need non-trivial handling of objects where the standard library is lacking convenient containers: handle duplication and COM with proper reference handling, unlike most DirectX code.

 

This, plus the rule of zero depends on your compiler being able to automatically generate appropriate default equivalents for move ctor/assignment operator.  That isn't available everywhere just yet (although the situation seems to be improving).  Many people will be using older compilers, so you can't blindly forget about the rule of 3/5.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement