IDDQD
IDDQD

Reputation: 3741

C++ most vexing vector element swap

I stumbled into this problem while working on a small project.

#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::vector<int*> v;
    for (int x = 1; x < 6; ++x)
    {
        int * a = new int(x);
        v.push_back(a);
    }

    unsigned int y = 4;
    for (auto a : v)
    {
        std::cout << "BEFORE SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl;
        std::swap(a, v[y]);
        std::cout << "AFTER SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl;
        std::cout << "==========" << std::endl;
        --y;
    }

    // for (std::vector<int*>::iterator it = v.begin(); it != v.end(); ++it)
    // {
    //     std::cout << "BEFORE SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl;
    //     std::swap(*it, v[y]);
    //     std::cout << "AFTER SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl;
    //     std::cout << "==========" << std::endl;
    //     --y;
    // }

    // inb4 "You forgot to deallocate!" This is an example.
}

At the end of the code, there are two loops which do the exact same task but in a different fashion.

The for loop with auto keyword produces this result with missing numbers:

BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 5
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1
==========
BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1
==========
BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1
==========
BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1
==========
BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 2, v[4] = 1
==========

The for loop with iterator works as expected:

BEFORE SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 5
AFTER SWAP: v[0] = 5, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1
==========
BEFORE SWAP: v[0] = 5, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1
AFTER SWAP: v[0] = 5, v[1] = 4, v[2] = 3, v[3] = 2, v[4] = 1
==========
BEFORE SWAP: v[0] = 5, v[1] = 4, v[2] = 3, v[3] = 2, v[4] = 1
AFTER SWAP: v[0] = 5, v[1] = 4, v[2] = 3, v[3] = 2, v[4] = 1
==========
BEFORE SWAP: v[0] = 5, v[1] = 4, v[2] = 3, v[3] = 2, v[4] = 1
AFTER SWAP: v[0] = 5, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1
==========
BEFORE SWAP: v[0] = 5, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 1
AFTER SWAP: v[0] = 1, v[1] = 2, v[2] = 3, v[3] = 4, v[4] = 5
==========

What is going on with the auto loop? Why do I lose values?

Here's a CPP.SH link to see for yourselves: http://cpp.sh/2ve3

Upvotes: 0

Views: 77

Answers (2)

Abhishek Panjabi
Abhishek Panjabi

Reputation: 439

Here copy of your array's value is stored in to variable "a". a is not the reference to ur array's value .that's why when you swap two variables it is swapped but in variable a .Not in the actual value of array. And as ur another parameter of swap is array's value it is taking value of variable a. That's why u r not getting desired output. The statement of auto a:v is actually statement as shown below:

a=v[0];
a=v[1]; (on next iteration) 

And so on . As you can see a is having just copy of array's value not reference. That's why you're getting this kind of output .

Upvotes: 0

dau_sama
dau_sama

Reputation: 4357

with for(auto a : v) you actually get a copy of the value, not the in place value in the array. You need to specify that you actually want the reference to it by declaring the loop as for(auto&a : v)

Functioning example:

for (auto& a : v)
{
    std::cout << "BEFORE SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl;
    std::swap(a, v[y]);
    std::cout << "AFTER SWAP: v[0] = " << *v[0] << ", v[1] = " << *v[1] << ", v[2] = " << *v[2] << ", v[3] = " << *v[3] << ", v[4] = " << *v[4] << std::endl;
    std::cout << "==========" << std::endl;
    --y;
}

if you try to trace the execution of your program now that you know that it was a value instead of a reference, you'll find out that the result makes sense.

Now that you understood how it works, you can just use the standard library to achieve what you try to do in just one call:

std::reverse(myvector.begin(),myvector.end());

Example at: http://www.cplusplus.com/reference/algorithm/reverse/?kw=reverse

Upvotes: 3

Related Questions