|
-
September 5th, 2002, 09:54 AM
#1
Why can't I pass by pointer
I have a function that takes a pointer as a parameter, this function changes the pointer but when I return from that fuction the pointer is still the same as it was before. Why is that?
int x = 6;
void function( int *n ) // pass in a pointer to an int
{
n = &x; // change the value of the pointer
}
void main ( )
{
int* pa = NULL;
// call the function to change the value of the pointer
function( pa );
// this doesn't work pa = NULL
if( pa )
cout << "Value of pa is " << *pa << endl;
}
I noticed that if I change the definition of function to void function( int *&n ) then it works the way I intend.
-
September 5th, 2002, 09:58 AM
#2
Try:
void function( int **n )
{
*n = &x;
}
In your original code you are passing your pointer by value.
You need to pass by reference (a pointer to your pointer).
regards, willchop
-
September 5th, 2002, 10:16 AM
#3
To change the value of a pointer, you need to pass the address of that pointer, as willchop showed with a pointer to a pointer.
You need to pass by reference (a pointer to your pointer).
These are two separate things.
I noticed that if I change the definition of function to void function( int *&n ) then it works the way I intend.
Pointer to pointer (int**) is better than pointer to reference (*&) because it's more obvious what's happening and not nearly as ugly.
Jeff
-
September 5th, 2002, 11:17 AM
#4
One advantage of using *& is that it ensures a valid value has been passed (vs. a NULL)
-
September 5th, 2002, 01:28 PM
#5
Pointer to pointer (int**) is better than pointer to reference (*&) because it's more obvious what's happening and not nearly as ugly.
I guess it's a matter of preference. I prefer references myself. Which is uglier:
Code:
(*p)++; // using the pointer to pointer
or
Code:
p++; // using the pointer reference
Maybe your argument/opinion would be more compelling if you said "safer".
Just my opinion,
John Flegert
-
September 5th, 2002, 02:06 PM
#6
Ya, I meant safer--more obvious to the developer what is expected. I avoid non-const references in favor of pointers.
But I still think *& is confusing and ugly.
Jeff
-
September 6th, 2002, 12:34 AM
#7
will &* achieve the same thing as *&?
-
September 6th, 2002, 03:31 AM
#8
No. I'm not sure that "&*" is even legal. If it is, it's almost certainly equivalent to plain "*".
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
September 6th, 2002, 03:46 AM
#9
BTW: I have to disagree with Jeff on one point. Pointer-to-pointer is not more obvious than reference-to-pointer. Pointer-to-pointer has multiple interpretations (2D-array for example), so it's not always obvious that it means that a value may be returned.
Code:
void foo(int ** i) // will it change "i", or does it expect a 2D array of int?
{
*i = new int[10]; // Ahhh, it's changing "i".
}
int main()
{
foo(0); // Oh, b*gger!
}
Interestingly, I had to think twice about the (single) statement in the body of foo()
Compare:
Code:
void foo(int *& i) // Mmmm - reference to non-const, "i" could be modified.
{
i = new int[10]; // And so it is.
}
int main()
{
foo(0); // DING! Compilation error.
}
As John said, it's a matter of preference, and I find that using a pointer rather than a reference to non-const is particularly ugly. (And I keep having to think 'do I need to put "*" in front or not?')
I would go so far as to say that "reference to non-const" is idiomatic for "this variable will have its value changed by this function". Pointer to non-const doesn't have that idiomatic meaning - it's ambiguous.
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
September 6th, 2002, 06:21 AM
#10
Graham said:
As John said, it's a matter of preference, and I find that using a pointer rather than a reference to non-const is particularly ugly. (And I keep having to think 'do I need to put "*" in front or not?')
I LIKE the ugliness; I like how a person looking at client code
can easily see if it's possible that a value can be modified without
having to look up the function in particular. The & doesn't
always mean that the variable will be modified, of course, but just
that the possibility is there.
With the double-pointer thing, you definitely have a point there.
I'm always looking for new ways to do things anyway so I like
coming on this board and finding other peoples' viewpoints.
Now all this thread needs is for someone to come and tell
everyone how they'd fail at a C++ job interview 
--Paul
-
September 6th, 2002, 08:44 AM
#11
Originally posted by PaulWendt
... The & doesn't always mean that the variable will be modified, of course, but just that the possibility is there. ...
--Paul
The same is true of the "*". What's important is the reference (or pointer) to non-const - if you're not going to change it, you'd make it a reference (or pointer) to const.
Also consider this:
Code:
void foo(MyClass*);
void bar(MyClass&);
Now, in both cases, the argument passed could be a derivative of MyClass. I would argue, however, that most people would tend not to assume that bar() relied on polymorphic behaviour - indeed, they would probably be surprised to discover that it did. Tell someone that foo() relies on polymorphic behaviour and they won't bat an eyelid. OK, maybe that's simplistic, and I don't want to get involved in a religious war here - if you prefer pointers to references, I ain't gonna stop you - I just want to present my arguments why I prefer references for the consideration of those who maybe haven't made their minds up yet.
I prefer to use reference to non-const idiomatically to mean "this argument will (probably) be modified". I can't impose that meaning on a pointer to non-const because it has too many other, well-established, meanings (pointer to array [that might be modified]; pointer to polymorphic object [that might be modified]; pointer to heap object [that might be modified], etc). Admittedly, the distinction is subtle, but I try to be consistent with it.
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
September 6th, 2002, 08:48 AM
#12
Hi, Graham.
I don't dispute anything you said, but I was actually meaning
something like this:
Code:
callSomeFunction(&variableToBeModified);
I think that the & makes it clearer that the variable can possibly
be modified ... without bothering to look at the function's
documentation [wherever it may be]. Granted, you'll want to look
at documentation anyway, but at first glance, I like the ugliness
of the pointer syntax better. I think I'm in the minority in this 
--Paul
-
September 6th, 2002, 09:05 AM
#13
Another option, just to bring it up.
Pointer to pointer (or reference) is used primarily to return memory allocated in the method to the caller. A better way would be to have it as the return value of the method using transfer-of-ownership with a smart pointer such as std::auto_ptr or boost::shared_ptr.
This removes ambiguities and ugliness of ** and the clumsiness of *&, as well as removing the responsibility of deallocating the memory from both the caller and the allocater.
Jeff
-
September 6th, 2002, 09:20 AM
#14
Jeff stated:
Pointer to pointer (or reference) is used primarily to return memory allocated in the method to the caller.
I actually rarely use it this way. Recently I wrote a parsing algorithm where all the sub-functions took a const pointer-to-reference (const char *& pStr).
However, IF you are allocating memory in this function and the function is more than trivial, Jeff's point should be considered. (I'm not a big fan of "smart pointers" and rarely use them.)
-
September 6th, 2002, 09:37 AM
#15
references and const references have very different meaning. I just want to clarify I was talking about non-const references.
I have to admit, I've rarely used smart pointers until recently. I have an object passed around a lot and the ownership of this object is far from obvious. I started down the path of reference counting it, where every user of the object addrefs and releases. Then I came across boost::smart_ptr, which handles the reference counting internally and deletes itself when it's no longer in use. It's really quite remarkable. It's fast, transparent, safe, and deallocates memory correctly. Most important, it removes the responsiblity of reference counting from the client, which can be an annoying source of bugs.
boost::smart_ptr can also safely be used in STL containers, while std::auto_ptr cannot.
Jeff
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|