views:

208

answers:

9

Can you give me an example when I can't pass argument by reference and I need to use pointer. I've found an example, but I'm not sure.

Suppose you have a class D derived from the base class B. You need pointer if you want do so:

void function(B* b){...}
int main{
  D* d;
  function(d);
}
+5  A: 

The single time where you can not use a reference and must use a pointer is if you allow the concept of "no argument" by passing a null pointer.

However, you might want to use pointers as arguments when you are actually storing a pointer to whatever was passed. Most C++ developpers will notice that you aren't using a reference and pay special attention to what your documentation says.

André Caron
One might argue that you even then don't *need* a pointer, if you write an object that has a nullable state. But whatyever.
John Dibling
Yes, but not all objects are nullable, especially when you're using RAII :-)
André Caron
@John Dibling: I am not that fan of the Nullable concept (at least built in), I much prefer the `boost::optional` hook, in order to distinguish by type what can and cannot be null.
Matthieu M.
A: 

the only reason is if you need to pass null. I.e you want to call the function saying 'I haven't got one of those'

pm100
+6  A: 

If there is a coding guideline (like Google's) that says to use pointer arguments, then that's what you do.

Otherwise, only declare your own function with pointer formal argument when

  • a nullpointer is a valid & meaningful actual argument, or

  • the actual argument is most naturally pointer already, or

  • you're going to store that pointer somewhere.

Possibly more cases, but I think you get the drift: when you have a choice (no coding guideline saying otherwise), prefer references.

Cheers & hth.,

Alf P. Steinbach
+1 for "the actual argument is most naturally pointer already" . Obvious example is that once you're talking about iterating, your concern is as much about where you are in the sequence as what object in the sequence you are looking at. E.g. http://stackoverflow.com/questions/3909784/how-do-i-find-a-particular-value-in-an-array-and-return-its-index/3909788#3909788 .
Brian
Of course, don't use Google's. It's stupid.
GMan
A: 

If you want to allow the lack of an object, you need to use pointers:

// This allows DoSomething to receive pointers to NULL, which cannot
// be done with references
void DoSomething(Something *pSomething)
{
  if (pSomething)
  {
    ...
  }
}

int main()
{
  Something *pSomething=NULL;

  DoSomething(pSomething);
}
Michael Goldshteyn
@Michael: instead of a function-long `if`, consider `if (!pSomething) { return; }` at the top :)
Matthieu M.
@Matthieu: But then the function would have more than one exit! .... :P
GMan
A: 

http://www.daniweb.com/forums/thread216353.html

Singly linked lists example were pointers and pointer of pointers are used as function parameters.

Jacob Nelson
A: 

I think that if you want to pass a function, you have to pass it by pointer. I don't see how you can pass the function by reference.

For example, take the following function:

#include <iostream>
#include "math.h"

void myfun (double value, size_t nofloops, double (*function)(double))
   {
   std::cout << value << std::endl;
   for (size_t i=0;i<nofloops;++i)
      {
      value = function(value);
      std::cout << value << std::endl;
      }
   std::cout << "------------------" << std::endl;
   }

void main()
   {
   myfun(100,10,sin);
   myfun(100,10,cos);
   myfun(100,10,sqrt);
   }

The function in this small utility executes the given function a number of times, taking the result as input in the next iteration. I can't see how you can pass the function by reference.

Patrick
Alf P. Steinbach
PS: When you pass a function by reference you get a very odd beast (that's probably why you thought it couldn't be done), a *read only reference*. It's not a reference to const, but you can't assign to it. Because you can't assign to a function, and when you think of a reference as just an alias, another name, then this makes sense.
Alf P. Steinbach
Apparently, some older C compilers allow "void main". See http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/legality-of-void-main.html.
Patrick
A: 

In C++ you can pass arguments by value, by reference or by pointer. But you should prefer to pass objects by reference, taking into account that it is a value semantic. Remember that depending on if you create an object by declaring a variable of that type, C++ allocates the object in the stack, but if you declare a pointer to that object you might initialize it, with the new operator (to really create the object instance in the heap). Also do not forget to use the delete operator for every object you created on the heap.

class B { B(){...} }
class D : B { D(): B{...}  } /*declares a class D, that derives from class B */
void f(B *b) {...} /* pointer semantics: the pointer b points to any object of the type B   */
void g(B &b) {...}  /* value semantics, because the type, the object is received by reference */
int main
{
    D d1;    /* object d1 is declared and created on the stack */
    D* d2;   /* pointer d2, to object of type D is declared */

    d2 = new D(); /* d2 allocates an object created in the heap (this calls the object constructor)*/

    f(&d1); /* calls the function f, pasing the reference of the object d1*/
    g(d2)   /* calls the function g, using value semantics */

    delete d2 /*de-allocates memory created on the heap (this calls the objects destructor)*/
}

The Scotts Meyers book is one of the most comprehensive guide regarding with C++.

ArceBrito
-1 ask to question, my example is very minimal, only to explain.
wiso
@wiso: In C++ you should minimize the usage of pointer. To know about guidelines for properly usage of references and pointers I recommend you to read the: HIGH·INTEGRITY C++ CODING STANDARD MANUAL.
ArceBrito
[HI CPP Rule 11.4 -- Use pass-by-reference in preference to pass by value or pass by pointer]. Pass by reference is more efficient than pass by value as the copy constructor of the object will not be invoked. Passing class objects by value can result in an object of a base class being passed instead of a copy of the actual object, reducing extendibility (not to mention slicing of the object). The C-style use of pointer types as function formal parameters in order to update object(s) in the calling function should be avoided. These formal parameters should be declared as reference types.
ArceBrito
Sorry, but the point is that my answer is not: "what's the difference about pass by value, pass by ...". My question is: "when I can't use pass by reference instead of pass by pointer?"
wiso
+1  A: 

Another case: if the thing you're passing is the last argument before varargs:

void fn1(A &a, ...); // Uh oh
void fn2(A *a, ...); // Good

I don't know if this is required by the standard, or is just a bug in the implementation of the C++ compiler I use.

Michael
The Standard only says that variable arguments must be the last argument, or maybe that there must be one preceeding argument. The type of that argument is definitely not mentioned.
DeadMG
A POD type right before `...` is not required in terms of declaring or defining a function, but it is necessary to usefully get those arguments back using `va_start()`. 18.7p3: "If the parameter [of `va_start`] is declared with a function, array, or reference type, or with a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined."
aschepler
Also, in this situation, I recommend creating an implicit conversion from `class A` to a POD struct which contains an `A*` pointer, and using that as the last named argument, so that users can call the function as if the first argument type were really `A` (or related reference).
aschepler
Indeed. The trouble I had was getting the arguments out, not declaring, or even calling, the function. Thanks for clearing up why that's the case, and for the record in MSVC++ 2005, "undefined" means "doesn't work" in this particular case, if you use a reference.
Michael
+1  A: 

Typically, you use pointers for one of two things:

  • Reassignability - you can't rebind a reference.
  • Null pointers - there's no such thing as a null reference.

If your intended use case does not need either of those two properties, use a reference. Else, use a pointer.

DeadMG