Reason to Pass a Pointer by Reference in C++

Reason to Pass a Pointer by Reference in C++?

You would want to pass a pointer by reference if you have a need to modify the pointer rather than the object that the pointer is pointing to.

This is similar to why double pointers are used; using a reference to a pointer is slightly safer than using pointers.

why can't we pass the pointer by reference in C?

From The C Programming Language - Second Edition (K&R 2):

5.2 Pointers and Function Arguments

Since C passes arguments to functions by value, there is no direct way
for the called function to alter a variable in the calling function.

...

Pointer arguments enable a function to access and change objects in
the function that called it.

If you understand that:

void fn1(int x) {
x = 5; /* a in main is not affected */
}
void fn2(int *x) {
*x = 5; /* a in main is affected */
}
int main(void) {
int a;

fn1(a);
fn2(&a);
return 0;
}

for the same reason:

void fn1(element *x) {
x = malloc(sizeof(element)); /* a in main is not affected */
}
void fn2(element **x) {
*x = malloc(sizeof(element)); /* a in main is affected */
}
int main(void) {
element *a;

fn1(a);
fn2(&a);
return 0;
}

As you can see, there is no difference between an int and a pointer to element, in the first example you need to pass a pointer to int, in the second one you need to pass a pointer to pointer to element.

Passing pointer by reference in C

In C, pass by reference is emulated by passing a pointer to the desired type. That means if you have an int * that you want to pass to a function that can be modified (i.e. a change to the int * is visible in the caller), then the function should accept an int **.

In your specific case however, this isn't what you want. You only need to pass an int * to your function which it can then dereference implicitly via the [] operator and change the elements of the array.

void sort(int *arr, int s, int e)
{
int temp = 0, i, j;
for (i=0;i<e;i++)
{
for (j=i+1;j<e;j++)
{
if (arr[i]>arr[j])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}

When pass-by-pointer is preferred to pass-by-reference in C++?

Some like pass-by-pointer better in cases where the object being passed is actually going to be modified. They use pass-by-const-reference when the object is being passed by reference in order to avoid a copy of the object, but will not be changed in the function.

In illustration, take the following functions:

int foo(int x);
int foo1(int &x);
int foo2(int *x);

Now in the code, I do the following:

int testInt = 0;

foo(testInt); // can't modify testInt
foo1(testInt); // can modify testInt

foo2(&testInt); // can modify testInt

In calling foo vs foo1, it's not apparent from the callers perspective (or a programmer reading the code) that the function can modify testInt without having to look at the signature of the function. Looking at foo2, a reader can easily see that the function may in fact modify the value of testInt because the function is receiving the address of the parameter. Note that this doesn't guarantee the object is actually modified, but that's where being consistent in the use of references vs. pointers helps. In general, if you want to follow this guideline consistently you should always pass const references when you want to avoid copies, and pass by pointer when you want to be able to modify the object.

Is passing pointer by value or by reference the same

What is the difference between passing a pointer by reference and passing a pointer by value in C?

There is no such thing as passing a pointer by reference in C, all variables are passed by value, even pointers.

My understanding is when you pass arguments to methods a new stack frame is created and those values are copied to different memory addresses unless passed by reference. If passed by reference the memory addresses are passed.

Again, the pointers are not passed by reference, a copy of the value stored in the pointer is passed, i.e. the address where it points to, you can test this by changing the value of the pointer inside the function, and check how that reflects on the original pointer, spoiler, it doesn't.

When working with pointers I noticed that if I pass a char by value and modify it in a different stack frame when I return back to the main stack frame the value of the ptr has been modified.*

What you are passing is an address, a memory location where some data is stored, when you change the data stored in that memory address it will be permanent, no matter where you do it, in fact that is one of the advantages of using pointers, for you to change the contents of some variable outside the scope where it's declared.

Why, or in what situations, would you pass an argument to a function as a reference (or pointer) in C++?

There are essentially three reasons why this is done.

Reduced memory usage

Every time you call a function the arguments are copied and passed. This isn't a big deal when you are passing around numbers. However when you are dealing with big chunks of memory, like objects, structs, arrays etc. this becomes very expensive.

So all complex types are typically passed as pointers. If you are throwing around objects you are always working with a pointer.

The const qualifier should be used in this instance to indicate that the variable won't be changed.

Modify the argument

Sometimes it is useful to modify the passed argument, though this should be avoided as bad style. The best example I think is modifying an array, for example a push() function. Another is modifying an objects public members, or when you want to return multiple values from a function.

Note that this can be a source of bugs. If you are modifying a passed variable it should be obvious from the name of the function that this is what you are doing.

Low level memory access

Anything which directly works with memory will want direct access to said memory. Standard practice in C but less common in C++. Look at functions like memcpy() and anything else from <string.h>.

When to pass a pointer to pointer as argument to functions in C++?

C++

In C++, you can pass by reference, and you do that when you want modifications of the parameter to affect the argument which the caller passed in. That is, passing by reference represents an out or in/out parameter.

You pass a pointer if the function wants a pointer (obviously), or if you want to signify an optional output parameter - since a reference always has to bind to something, but a pointer can be null.

By the same logic, pass a pointer to pointer if the function actually needs double pointers (very rare in C++) or if you want to signify an optional [in-]out parameter of pointer type (also quite rare).

Here are some examples (contrived, but should demonstrate the thing):

int square(int x)  //pass int by value
{ return x * x; }

void squareRoots(double in, double &plus, double &minus) //pass double by reference
{
plus = sqrt(in);
minus = -plus;
}

int toNumber(String s, bool *ok = nullptr) //optional out parameter
{
try {
int val = s.toNumber();
if (ok)
*ok = true;
return val;
} catch (NotANumber &) {
if (ok)
*ok = false;
return 0;
}
}

int computeAge(Person *person) //pass pointer by value
{
if (!person)
return -1;
else
return now() - person->dateOfBirth();
}

bool createPerson(Person * &person) //pass pointer by reference
{
if (tooManyPeople())
return false;
person = new Person();
return true;
}

int sum(int **values) //pass double pointer by value
{
if (!values)
return 0;
int res = 0;
while (*values) {
res += **values;
++values;
}
return res;
}

bool allocate(int ** &arr) //pass double pointer by reference
{
if (!enoughMemory())
return false;
arr = new int*[1024]; // array of 1024 pointers to int
return true;
}

bool newNode(Node **node = nullptr) //optional out parameter
{
Node *added = dataStructure.createNode();
if (node)
*node = added;
return added;
}

(Note 1: I am only talking about non-const references here, since that's relevant to the pass by pointer vs. pass by reference. Passing by const-reference usually means "the object is too big to copy needlessly," and does not apply really when pointers to pointers could be involved).

(Note 2: The above examples are horrible in that they use owning raw pointers, dynamic array allocation etc. In actual C++, you would use smart pointers, std::vector etc. instead. That's why pointers to pointer are rare in C++).


C

In C, double pointers are more common, since C does not have a reference type. Therefore, you also use a pointer to "pass by reference." Where & is used in a parameter type in the C++ examples above, * would be used in C (and dereferenced when manipulating the parameter). One example:

void squareRoots(double in, double *plus, double *minus)  //pass double "by reference"
{
*plus = sqrt(in);
*minus = -*plus;
}

Can someone explain what purpose passing by pointer and passing by reference have in c++?

In the first example you gave you are passing the parameters by value, this creates a copy of the variables in memory and the function operates on the copy. This means that the original value of x and y do not get modified, only their copies do. When the function ends the copies are destroyed and the original values remain untouched.

In the second example you pass in a pointer, a pointer just "points" to the memory where your variable x and y are stored. When you de-reference (the * operator) a pointer you can use the variable as you would any other, meaning that doing:

*x = *y;

You are actually setting the variable at memory address x to the value of the variable at memory address y. Unlike the first code snippet this changes the value of the variable globally.

In short, passing by value creates a duplicate of x for you function to use. After the function finishes x is destroyed and the original x variable remains untouched. Passing by pointer or reference means you pass in where x is stored, and then access the x variable. When the function ends x remains modified.

Why do they exist?

Simply put it is useful for large objects to pass the pointer to them instead, as creating duplicates of classes or structures which have large memory footprints is really slow.

When should you pass by value

When you simply want a copy of the data but not to modify the original, usually because modifying the original is unnecessary or harmful to the application.

When should you pass by reference

When you want to modify the original value of the variable within a function.

When should I use a pointer?

When you want to modify the variable in memory or assign an entirely new variable to that memory address.

Why passing a pointer by reference here causes an error?

The getLeft method returns a copy of the left member variable, so even if your code compiled it would not alter left. However it doesn't compile because of the rule that you cannot bind a reference to a temporary.

Several solutions are possible, the one that seems the best to me is to replace getLeft with left and getRight with right.

       rec_insertBST(subRoot->right, key);

This will require changing access permissions or granting friendship.

Another alternative would be to have getLeft and getRight return references.

Are there benefits of passing by pointer over passing by reference in C++?

A pointer can receive a NULL parameter, a reference parameter can not. If there's ever a chance that you could want to pass "no object", then use a pointer instead of a reference.

Also, passing by pointer allows you to explicitly see at the call site whether the object is passed by value or by reference:

// Is mySprite passed by value or by reference?  You can't tell 
// without looking at the definition of func()
func(mySprite);

// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);


Related Topics



Leave a reply



Submit