tags:

views:

413

answers:

9

I'm currently doing my first real project in C++ and so, fairly new to pointers. I know what they are and have read some basic usage rules. Probably not enough since I still do not really understand when to use them, and when not.

The problem is that most places just mention that most people either overuse them or underuse them. My question is, when to use them, and when not?.

Currently, in many cases i'm asking myself, should I use a pointer here or just pass the variable itself to the function.

For instance, I know that you can send a pointer to a function so the function can actually alter the variable itself instead of a copy of it. But when you just need to get some information of the object once (for instance the method needs a getValue() something), are pointers usefull in that case?

I would love to see either reactions but also links that might be helpfull. Since it is my first time using C++ I do not yet have a good C++ book (was thinking about buying one if I keep on using c++ which I probably will).

+2  A: 

Use it whenever you are dealing with allocated memory or passing arguments by reference to a method; I don't think there is a rule for not using pointers.

Otávio Décio
this is c++ so you you would use a reference in preference to pointers probably
frankster
+4  A: 

1) I tend to use member variables scoped with the class. They are constructed in the initializer of the class, and I don't need to worry about pointers.

2) You can pass by reference to a function, and not worry about passing pointers. This effectively will pass a pointer to the method / function that can be used as if you passed the class, but without the overhead of copying the class itself.

3) If I need to control the lifetime of an object that is independent of my main application architecture's classes... then I will use an auto_ptr from the STL to automatically handle the pointer's destruction when no one longer references it. Check it out - it's the way to go.

Kieveli
A: 

Generally, when you can use references instead of pointers it is a good idea. A reference must have a target (no NULL pointer violations), they allow the same semantics as pointers when being passed as arguments to a function, and they are generally nicer to use for beginners (or those not coming from a C background).

Pointers are required when you want to do dynamic allocation of memory; when you need to deal with an unknown amount of things that will be later specified. In this case the interface to access memory is through new and delete which deal in pointers.

ezpz
+6  A: 

From the c++ faq:

Use references when you can, and pointers when you have to.

http://www.parashift.com/c++-faq-lite/references.html#faq-8.6

Kristian
+16  A: 

For the do's and dont's of C++:

Effective C++ and More Effective C++ by Scott Meyers.

For pointers (and references):

  • use pass by value if the type fits into 4 Bytes and don't want to have it changed after the return of the call.
  • use pass by reference to const if the type is larger and you don't want to have it changed after the return of the call.
  • use pass by reference if the parameter can't be NULL
  • use a pointer otherwise.


dont't use raw pointers if you don't need to. Most of the time, a smart pointer (see Boost) is the better option.

Tobias Langner
What's with those 4 bytes on 64bt architectures?
sbi
for the first rule i would say "use pass by value of sizeof(T) > sizeof(int)...."
Evan Teran
As for the pass-by-reference thing for larger types, http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ is worth reading.
jalf
@Evan: What I was getting at was that the `4`, as all magic numbers, is arbitrary and thus bad. AFAIK, `sizeof(int)` would be bad, too, on IA64, because `int` is 32bit there. (Don't get me started...) And I do remember ages ago someone on c.l.c++.m mentioning a C++ compiler that would never pass structs by value, no matter how small. To sum up my point: `4` (and `sizeof(int)` is probably fine for "common compilers on common 32bit architectures".
sbi
Of course 4 - as a magic number - is "bad". I used it because it's easier to remember and most of the development is still 32bit. See it as a hint to look into the size of types and how it compiles. Once you understand what the compiler does, you'll really understand what to use when.
Tobias Langner
@sbi: true about `sizeof(int)`, perhaps `sizeof(long)` is a better metric since it will be larger on 64-bit systems. My point was to not hard code it, but instead base it on the native types for that arch/compiler.
Evan Teran
A: 

My philosophy is to always pass by value, unless you need to modify the variable passed or copying the object is expensive. In both these cases, consider using a reference instead of a pointer first: if you don't need to change which object you're referencing, nor do you need a possible extremal value (NULL pointer), you can use a reference.

Don't forget about iterators either.

suszterpatt
A: 

All good answers above. Additionally, if you are performing some processor-intensive work, it's important to realize that dereferencing a pointer will likely be a cache miss on your processor. It's a good idea to keep your data accessible with minimal pointer dereferences.

San Jacinto
A: 
  1. Class attribute: pointer
  2. Variables declared in methods: no pointers, so we avoid memory leaks.

In this way, prevent memory leaks and controlle attribute's consistency.

Salu2.

Miguel Angel
+1  A: 

My rules of thumb:

  1. Always pass function parameters as const references,
  2. unless they are built-in types, in which case they are copied (and const/non-const becomes a question of style as the caller isn't affected) or
  3. unless they are meant to be changed inside the function so that the changes reflect at the caller's, in which case they are passed by non-const reference or
  4. unless the function should be callable even if callers don't have an object to pass, then they are passed as pointers, so that callers can pass in NULL pointers instead (apply #1 and #3 to decide whether to pass per const T* or per T*)

Streams must always be passed around as non-const references.

sbi