• Advertisement
Sign in to follow this  

Sending a pointer to a function

This topic is 3480 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

This is what Im trying to do:
void foo( int* bar )
{
   // lets make a memory leak!
   bar = new int(5);
}

int main ()
{
   int* myint = NULL;
   foo( myint );

   return 1;
}
I want to know why "myint" is still NULL after the call to foo(). Must I do something more like the following?
void foo( int** bar )
{
   *bar = new int(5);
}

Share this post


Link to post
Share on other sites
Advertisement
Yes, you either need a pointer to a pointer (like you do in your 2nd example), or a reference to a pointer. This is essentially the same as a pointer to a pointer, but it looks nicer. ;)



void foo( int*& bar )
{
bar = new int(5);
}








This is because your function really gets a COPY of what you pass it in the argument list. Thus if you didn't give it a pointer to a pointer (or reference to a pointer), it would make a copy of your pointer, then set that to point at something ... all the while leaving your original pointer unchanged.


P.S. Beware that in your example where you use a pointer to a pointer, it may still be a good idea to check for null (which is not necessary when using a reference because references can't be null).


void foo( int** bar )
{
if ( ! bar )
{
return;
}
*bar = new int(5);
}



Share this post


Link to post
Share on other sites
Well, myint is a local variable of the main function, which was passed by value (and therefore copied) to another function. This means that the variable simply could not have been modified.

The short answer is, "don't do this". Unlike C, in C++, you should always return your results instead of altering the arguments, otherwise you will get into trouble with constructor semantics.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
The short answer is, "don't do this". Unlike C, in C++, you should always return your results instead of altering the arguments, otherwise you will get into trouble with constructor semantics.


Right, Ive been told this before but what if a have a huge class or struct in which only one attribute needs to be changed.

class Huge
{
public:
Huge() : a(0) {}
Huge( Huge& other ) : a(other.a) {}

int a;
// many other attributes
};

Huge convert( Huge original )
{
Huge temp( original ); // copy
temp.a = 5; // change
return temp; // copy again
}

void main()
{
Huge myhuge;
myhuge = convert( myhuge );
cout << myhuge.a << endl;
}


In this example, isnt the "Huge" instance copied when calling the function? And a new instance is then created by copying "original" (I hope I got the syntax right for the copy constructor btw) and then yet again when the "temp" instance is returned (since its local)?

I thought it would be nicer to have something along the lines of what I tried to achieve in my first post:

void convert( Huge* original )
{
original->a = 5;
}


Red Ant already answered my question but I would like to discuss this. Where were you going about the above mentioned strategy would make constructors troublesome?

Share this post


Link to post
Share on other sites
Why are you exposing the member variable as public? You could make convert a member function of Huge and make it only modify the one required field. That's what classes are for.

If for some reason you need to use non-member function that modifies the member variable (either directly or via getters/setters, it's irrelevant), I'd pass the Huge object via non-const reference, modify it through that and make it clear that modify will, well, modify the passed-in object.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mizipzor
Quote:
Original post by ToohrVyk
The short answer is, "don't do this". Unlike C, in C++, you should always return your results instead of altering the arguments, otherwise you will get into trouble with constructor semantics.


Right, Ive been told this before but what if a have a huge class or struct in which only one attribute needs to be changed.


This is an entirely different thing. In your original example, you created a new value and sent it to the caller through an argument instead of through the return value.

In your second example, it is the caller who sends the function a value as an argument, and the function sends nothing to the caller (it merely does some work on the argument). In short, if you need to create a new object, use return, and if you need to alter an existing object, use an argument.

Note, however, that your second example is unsafe. You will need to do something like:
void convert( Huge* original )
{
if (original)
original->a = 5;
else
; // Do something relevant here
}


In practice, if you need a valid argument (a null pointer being an invalid argument), you should be using a reference instead.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mizipzor
I thought it would be nicer to have something along the lines of what I tried to achieve in my first post:

But that works fine. Here you're changing the contents of the memory that the pointer points to, NOT the pointer itself (unlike your first example).

So the pointer is copied (pass by value), but not what it points to.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mizipzor
In this example, isnt the "Huge" instance copied when calling the function?


Probably.

Quote:
And a new instance is then created by copying "original" (I hope I got the syntax right for the copy constructor btw)


Probably; which is exactly why you wouldn't write the code like this. You were already given a copy; if you want to work on a copy, work on the copy you're given rather than re-copying.

Quote:
and then yet again when the "temp" instance is returned (since its local)?


Maybe. There exists such a thing as "named return value optimization", whereby the compiler basically figures out to use the space on the stack where the return value goes, for the 'temp' variable.

Of course, all of that could go away, if the function gets inlined, and the code assigns the result back to the original variable, and the compiler is smart enough/doesn't have its hands tied by a weird pointer aliasing issue.

Quote:
I thought it would be nicer to have something along the lines of what I tried to achieve in my first post:

*** Source Snippet Removed ***


Well, you could do that, but normal OO practice is to let work be done by the objects that have the best access to the needed data:


class Huge
{
public:
Huge() : a(0) {}
Huge( Huge& other ) : a(other.a) {}

int a;
// many other attributes

void convert() { a = 5; } // <-- there you go.
};



... And the net effect is that the object is not copied after all (since 'this' is a pointer).

Share this post


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

  • Advertisement