Thursday, April 28, 2011

In C++, are changes to pointers passed to a function reflected in the calling function?

If I pass a pointer P from function f1 to function f2, and modify the contents of P in f2, will these modifications be reflected in f1 automatically?

For example, if I need to delete the first node in a linked list:

void f2( Node *p)
{
    Node *tmp = p;
    p = p -> next;
    delete tmp;
}

Will the changes made to P be reflected in the calling function, or will it now point to a memory space that has been deallocated?

( My intuitive answer here is no, changes are not reflected. However, good sources tell me that the above code will work. Can someone take the time to give the answer and explain the reasoning behind it also please? Also, if the above code is faulty, how can we achieve this without using a return type? )

From stackoverflow
  • If I pass a pointer P from function f1 to function f2, and modify the contents of P in f2, will these modifications be reflected in f1 automatically?

    No. Since C and C++ implement pass-by-value, the value of the pointer is copied when it’s passed to the function. Only that local copy is modified, and the value is not copied back when the function is left (this would be copy-by-reference which a few languages support).

    If you want the original value to be modified, you need to pass a reference to the pointer, i.e. change your signature of f2 to read:

    void f2( Node*& p)
    

    However, your f2 not only changes the pointer p, it also changes its underlying value (= the value being pointed to) by using delete. That change is indeed visible to the caller.

    Bart van Ingen Schenau : In addition: If you want to have a value changed in C, your only option is to pass the address. i.e. `void f2( Node** p)`.
    Steve Jessop : "it also changes its underlying value": here "underlying value" == "referand"?
    Konrad Rudolph : @Steve: underlying value == pointee (== referand?).
    Steve Jessop : Yes. If we want to be pedantic, the high-faluting technical term used in 3.7.3.2/4 of the standard is "the storage referenced by the pointer" ;-)
  • This will work, althrough not the way you want to.

    If you call it like:

    Node* mynode = new Node(); /*fill data*/
    f2(mynode);
    

    -> there will be the content of mynode undefined.

    it will pass the value of the pointer to another function, and the value (p) will be local for function f2. If you want to modify it, use this way:

    Node* mynode = new Node(); /*fill data*/
    f2(&mynode);
    
    void f2(Node** p)
    {
     Node* tmp = *p;
     *p = (*p)->next;
     delete tmp;
    }
    
    Konrad Rudolph : No, it’s not undefined – it just remains unchanged (or do you mean “pointee” by “content”?).
    Steve Jessop : The value is unchanged, but using that value as a pointer in any way (for example comparing it to another pointer value including a null pointer) is undefined. By examining it byte-by-byte, you could validly observe that the representation hasn't changed.
    Konrad Rudolph : @Steve: since it’s so much fun …: Using the pointer in a comparison is *only* undefined if it doesn’t point to the element of an array (or one past the last element of the array). ;-) So yes, this example code would indeed be invalid – provided `new` isn’t overloaded to allocate storage from inside an array buffer.
    Steve Jessop : @Konrad: touché. My unstated assumption is that `delete` calls a standard deallocation function on its operand.

0 comments:

Post a Comment