21

I'm working on a function to swap pointers and I can't figure out why this isn't working. When I print out r and s in the swap function the values are swapped, which leads me to believe I'm manipulating a copy of which I don't understand because I pass by reference of p and q.

void swap(int *r, int *s)
{
    int *pSwap = r;
    r = s;
    s = pSwap;
    return;
}

int main()
{
    int p = 7;
    int q = 9;  
    swap(&p, &q);
    cout << "p = " << p << "q= " << q << endl;
    return 0;
}

Prints: p = 7q = 9

6
  • 2
    You're manipulating copies of pointers, not the data they point to. It's easier just to std::swap(p, q);. Or, if the proposal actually makes it in, p :=: q; sometime in the future. Commented Mar 28, 2013 at 1:46
  • 3
    @chris: Waaaat. Can you link to said proposal? (Searching for symbols is hard.) Commented Mar 28, 2013 at 1:48
  • 1
    @GManNickG, Yeah, sure. Here you go. I had high doubts of it making it in. Commented Mar 28, 2013 at 1:48
  • @chris: Sorry I'm new trying to learn this, how am I manipulating copies if I passed by reference? Commented Mar 28, 2013 at 1:53
  • 2
    @MK: You need to dereference the pointers. But this is error-prone because they could be null, so you should use references instead. (Note you are not, in fact, passing anything by reference. You're passing values, which happen to pointers.) Commented Mar 28, 2013 at 1:55

7 Answers 7

28

Inside your swap function, you are just changing the direction of pointers, i.e., change the objects the pointer points to (here, specifically it is the address of the objects p and q). the objects pointed by the pointer are not changed at all.

You can use std::swap directly. Or code your swap function like the following:

void swap(int *r, int *s)
{
   int temp = *r;
   *r = *s;
   *s = temp;
   return;
} 
Sign up to request clarification or add additional context in comments.

6 Comments

It is not clear to me if OP wants to swap pointers or the values the pointers point to.
@ShafikYaghmour What OP did was swapping pointers, so I guess OP wants to swap values pointers point to.
@MK Can you modify your question so that it is clear that you do not want to modify pointers but their contents.
@ShafikYaghmour, You can't physically swap the addresses of two things, though.
Isn't the return statement useless?
|
13

The accepted answer by taocp doesn't quite swap pointers either. The following is the correct way to swap pointers.

void swap(int **r, int **s)
{
    int *pSwap = *r;
    *r = *s;
    *s = pSwap;
}

int main()
{
    int *p = new int(7);
    int *q = new int(9);

    cout << "p = " << std::hex << p << std::endl;
    cout << "q = " << std::hex << q << std::endl << std::endl;

    swap(&p, &q);

    cout << "p = " << std::hex << p << std::endl;
    cout << "q = " << std::hex << q << std::endl << std::endl;

    cout << "p = " << *p << " q= " << *q << endl;
    return 0;
}

Output on my machine:

p = 0x2bf6440
q = 0x2bf6460

p = 0x2bf6460
q = 0x2bf6440

p = 9 q= 7

3 Comments

I know that using void * (in this case void **) is not deemed as best practice, but regarding that each pointer is actually std::size_t (unsigned) variable representing 32/64 bit memory slot. Wouldn't having void swap( void** A, void ** B) function work better with other data types as well?
You should probably delete the memory you allocated. Does not really matter in this example but to be consistent and also it's good practise.
answering to my own comment form 2021. having void ** works, only thing is that one needs to convert and recast type after use : swap( (void **)&p, (void **)&q). Only thing that can make a memory leak is if used with <vector>s since they can change their whole memory and swap will simply swap memory that isn't used anymore. So use well with data you know.
1

The line r=s is setting a copy of the pointer r to the copy of the pointer s.

Instead (if you do not want to use the std:swap) you need to do this

void swap(int *r, int *s)
{
    int tmp = *r;
    *r = *s;
    *s = tmp;
}

Comments

1

You passed references to your values, which are not pointers. So, the compiler creates temporary (int*)'s and passes those to the function.

Think about what p and q are: they are variables, which means they are slots allocated somewhere in memory (on the stack, but that's not important here). In what sense can you talk about "swapping the pointers"? It's not like you can swap the addresses of the slots.

What you can do is swap the value of two containers that hold the actual addresses - and those are pointers.

If you want to swap pointers, you have to create pointer variables, and pass those to the function.

Like this:

int p = 7;
int q = 9;

int *pptr = &p;
int *qptr = &q;
swap(pptr, qptr);
cout << "p = " << *pptr << "q= " << *qptr << endl;
return 0;

Comments

0

You are not passing by reference in your example. This version passes by reference,

void swap2(int &r, int &s)
{
    int pSwap = r;
    r = s;
    s = pSwap;
    return;
}

int main()
{
    int p = 7;
    int q = 9;
    swap2(p, q);
    cout << "p = " << p << "q= " << q << endl;
    return 0;
}

Passing by reference is not the same as passing by value or by pointer. See C++ tutorials on the web for an explanation. My brain is too small to waste cells storing the fine details I can find on the web easily.

1 Comment

That swaps the values, not any pointers. By declaring the function as taking references, you just changed the semantics of the swap function. r = s when r and s are references means the same thing as *p = *q when p and q are pointers. Check it on your debugger by observing the memory locations where p and q are stored.
0
void swapPointer(int* &ptr1, int* &ptr2) {
    int* temp = ptr2;
    ptr2 = ptr1;
    ptr1 = temp;
}

It can be resolve by using reference.

Comments

-2

If you are into the dark arts of C I suggest this macro:

#define PTR_SWAP(x, y)  float* temp = x; x = y; y = temp;

So far this has worked for me.

2 Comments

Question is about C++.
@balu C++ includes this functionality regardless.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.