Why doesn't replacing two values ​​based on pointers work out of scope?

I have not programmed in C ++ for several years, so I decided to update my memories with pointers.

In the classic example of replacing two numbers, an example

void swapPointersClassic(double *num1, double *num2) { double temp; temp = *num1; *num1 = *num2; *num2 = temp; } 

This allows us to call a function call like swapPointersClassic(&foo, &bar); , and since we pass the memory addresses of both variables foo and bar, the function will retrieve the values ​​and perform the exchange. But I began to wonder why I can not do the following?

 void swapPointers(double *num1, double *num2) { double *temp; temp = num1; num1 = num2; num2 = temp; } 

It seems to me that it makes more sense to me, because we need to create enough temporary storage to store the memory address num1 (instead of a full temporary storage to store the double value * num1). However, it seems that the scope of the function limits the effect of replacing the pointer. After making a call to swapPointers(&foo, &bar); , I see that inside the swapPointers function, foo and bar do indeed swap places. As soon as we exit the swapPointers function, foo and bar are no longer replaced. Can someone help me understand why this is so? This behavior reminds me of a typical cost-based approach, but we are indicating pointers here. So, we can concern only the values ​​indicated by these pointers, but not the pointers themselves?

+8
c ++ pointers swap
source share
8 answers

In fact, you really don't follow the sign. You pass two pointers by value. Missing missing pointers - you must dereference them. The act of dereferencing (copies) of pointers makes magic happen, and this is the actual place where traversal of the area is achieved.

Changing function arguments is local to the function, even if the arguments themselves are pointers. You must dereference them in order to access the memory that they pointed to (again, "passing by pointer" is more than passing pointers - passing pointers and using them properly).

Also consider the following. If your second approach worked and the two pointers were replaced, that would mean swapping the addresses of the variables. This is not entirely clear.

By the way, in C ++ we have a true pass-by-reference calling convention, so there is no need to bother with pointers:

 void swap(double &a, double &b) { double temp = a; a = b; b = temp; } float a = 1, b = 2; swap(a, b); 

(It's just an implementation issue that the compiler is likely to understand this behavior by actually using pointers, but at least you have no headache.)

+5
source share

If you want to change pointers, not their values, you need to pass a pointer to a pointer:

 void swapPointers(double** num1, double** num2) { double* temp = *num1; *num1 = *num2; *num2 = temp; } 

You can see an example at: http://ideone.com/iklCta

You can even work with links:

 void swapPointers(double*& num1, double*& num2) { double* temp = num1; num1 = num2; num2 = temp; } 

Example: http://ideone.com/w4k9mV

This is useful when you work with huge objects (for example: image data), and you do not want to move a lot of memory, but only links.

+5
source share

This is a good question, but as soon as you understand it, use std::swap or std::iter_swap instead of writing your own.

If foo and bar are pointers, calling std::swap(foo, bar) will swap addresses between the two pointers. Calling std::swap(*foo, *bar) or std::iter_swap(foo, bar) will dereference pointers and exchange objects pointed to by pointers.

+2
source share

You yourself pass pointers by value; num1 and num2 are local copies of pointers calling the calling function c. Thus, the replacement is not displayed on the calling point when the function exits since changes were made only to variables that are local to the function.

Instead, change the function to get pointers to references, and your swap code will work as intended.

 void swapPointers(double*& num1, double*& num2) { ... } 

Now your function parameters are aliases of pointers passed to the calling program, and everything you do with them will also affect pointers in the context of the caller.

0
source share

When you call

 swapPointersClassic(&foo, &bar) 

You take the address of two elements onto the stack . These values ​​are transferred as temporary and are copied by value . In your body, you swap functions where these time points indicate, but do not move to where foo and bar indicate.

Most importantly, foo and bar live on the stack . You cannot change where the variables live on the C ++ stack. The value is mapped onto a spot on the stack and lives there. You can get a pointer to where this value lives in order to go through the pointer (similar to pass-by-reference), but just changing where these temporary pointers indicate that you are not changing where the object the object points to .

0
source share

When you pass double *num1 to a function, you pass a pointer by value. This creates a variable in the function area that contains the address double. When you assign this, you change the value of the pointer in the function area.

Just as you must pass a pointer to a double, find it and assign it to replace the double, you need to pass a pointer to a pointer, find it and assign it to exchange a pointer.

0
source share

Pointers 101: A pointer is a piece of paper with the address of the house on it.

By writing & bar, you take a house called bar and write down your address on an anonymous piece of scrap.

Then you call the function with this pointer as an argument. What happens here is that the function creates another copy of a piece of paper.

Then your swap function takes two such local copies and swaps what address is written on them.

So nothing goes beyond the function. Clear?

Now, in principle, even if the address function did not have a copy with which you are working, there is broken paper with home addresses on them. No changes on such paper can actually move data stored in the bar at home or foo.

0
source share

Since the correct answer to this question has already been published, I would just make some things clear.

Exchanging the values ​​of two variables using references is bad practice in general and should be avoided. the reason is that links should not be rewritten. Take a look at the following code:

 1. void swap(double &a, double &b) 2. { 3. double temp = a; 4. a = b; //Not what you think 5. b = temp; 6. } 7. 8. float a = 1, b = 2; 9. swap(a, b); 

on lines 4 and 5, you are clearly violating the general rule - "Never rewrite links."

If you really need to change the value of the variable (s), always prefer to "pass by pointers" rather than "pass by reference". The following code makes sense and has a good IMO practice.

 1. void swapPointersClassic(double *num1, double *num2) 2. { 3. double temp; 4. temp = *num1; 5. *num1 = *num2; 6. *num2 = temp; 7. } 8. 9. float a = 1, b = 2; 10. swap(&a, &b); 

They agreed that the links are cleaner and easier to use, and they better deal with hidden information, as you saw in the first example. However, links cannot be reassigned. If you need to point to one object first and then to another, you must use a pointer.

Rule of thumb:

  • DO NOT use pointers if links will work.
  • DO NOT try to reassign the reference to another variable. You can not.
0
source share

All Articles