Re: pass by Reference/value ???

From: John Carson (donaldquixote_at_datafast.net.au)
Date: 02/12/04


Date: Thu, 12 Feb 2004 15:39:21 +1100


"dumboo" <vthe2@yahoo.com> wrote in message
news:c0et85$16gqsh$1@ID-211285.news.uni-berlin.de
> hi there
> i m little bit confused over the following problem, i have understood
> wt the following code is doing...but not able to get the actual
> techinical stuff.....i have had a lot of hot debate over the
> following code whether its pass by reference or pass by value...hope
> somebody clears it up :-)
> void foo(char *s)
> {
> s = new char[10];
> strcpy(s, "gotit");
> }
>
> int main()
> {
> char *s;
> foo(s);
> cout<<s;
> delete s;
>
> return 0;
> }
>
> regards

There is some confusion here resulting from C++'s origin in C. The C
language does not have C++-style references. Accordingly, if you want a
function in C to modify something, you need to pass it a pointer to the
thing to be modified. In C, this is called "passing by reference". Now
consider your function:

void foo(char *s)
{
    s = new char[10];
    strcpy(s, "gotit");
}

In C, this would be called "passing by reference". The important thing to
note, however, is that the thing that is passed by reference is *not* the
variable s but what s points to, i.e., s is passed by value and what s
points to is passed by reference. What this means is that

1. foo receives a local copy of s and any changes that it makes to s only
affect that local copy.
2. the copy of s that foo receives points to the same memory area as the
original s did, so any changes made to what s points to have the same effect
within the function as they would have in the place from which the function
is called.

In your line:

    s = new char[10];

you are changing the local copy of s, which has no effect on the original s.
Thus cout in main() is being applied to the uninitialised s.

If you want to modify s, then there are two ways to go about it. The C-style
approach is to pass the address of s rather than s itself, as follows:

void foo(char **ps)
{
    *ps = new char[10];
    strcpy(*ps, "gotit");
}

int main()
{
    char *s;
    foo(&s);
    cout << s;
    delete[] s;
    return 0;
}

Note:

1. Since s is a pointer, a variable storing the address of s is a pointer to
pointer. Thus there is a double asterisk in the definition of foo's
parameter. ps is a pointer to s, so *ps gives the original s. Hence *ps
replaces s in your foo function.
2. foo is called with an argument of &s rather than with an argument of s.
3. I have changed your original delete to the (correct) array form of
delete[].

The C++-style approach is to use references as follows:

void foo(char *& s)
{
    s = new char[10];
    strcpy(s, "gotit");
}
int main()
{
    char *s;
    foo(s);
    cout << s;
    delete[] s;
    return 0;
}

This involves the least change to your code. All you need to do is replace

void foo(char *s)

with

void foo(char *& s)

i.e., you only need add the & symbol. This change means that s itself ---
and not just what it points to --- is "passed by reference" (in the C++
sense of that term). This means that foo operates on the original s --- no
local copy is made --- so that any changes that foo makes to s affect the
original.

-- 
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)


Relevant Pages

  • Re: Strong thread safety and lock free?
    ... you definitely can pack pointer and counter into single word. ... No, there is no emulation of locks, just 2 reference counters ... Automatic alignment but typically no explicit alignment required ... static void debuglog(const char* fmt, ...
    (comp.programming.threads)
  • Re: manipulating void* in array
    ... The correct type is void** as Dave pointed out. ... But how does foo* ... I thought your key pointer type was void*. ... > whole array of *copies* of my foo things. ...
    (comp.lang.c)
  • Re: void types and how to use them efficiently?
    ... Where i use void as a generic object. ... this is also used for accessing info structs (per object, ... another approach is what is known as tagged references, ... to resolve the index to a pointer), it usually improves performance for many ...
    (comp.lang.c)
  • Re: Incrementing a void pointer. Legal C99?
    ... the behaviour is equivalent to incrementing a char pointer. ... "void *"), but allow the latter (arithmetic on a pointer that points ... a = &foo; ...
    (comp.lang.c)
  • Re: basic question about references
    ... It expects a reference, ... not a pointer. ... void f; // a reference ... introduced for operator overloading because using ...
    (alt.comp.lang.learn.c-cpp)