C ++最烦人的矢量元素交换

时间:2016-06-09 04:01:18

标签: c++

我在处理一个小项目时偶然发现了这个问题。

#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.
}

在代码的最后,有两个循环执行完全相同的任务但是以不同的方式。

带有auto关键字的for循环会产生缺少数字的结果:

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
==========

带迭代器的for循环按预期工作:

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
==========

auto循环是怎么回事?为什么我会失去价值观?

这是一个CPP.SH链接,可以自己查看:http://cpp.sh/2ve3

2 个答案:

答案 0 :(得分:3)

for(auto a : v) 你实际上得到的是值的副本,而不是数组中的就地值。 您需要通过将循环声明为for(auto&a : v)

来指定您实际需要引用它

功能示例:

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;
}

如果您现在尝试跟踪程序的执行情况,因为您知道它是一个值而不是引用,那么您将发现结果是有意义的。

现在您已了解其工作原理,您只需使用标准库即可实现您在一次通话中尝试执行的操作:

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

示例: http://www.cplusplus.com/reference/algorithm/reverse/?kw=reverse

答案 1 :(得分:0)

此处数组值的副本存储在变量&#34; a&#34;中。 a不是对ur数组的值的引用。这就是为什么当你交换两个变量时它被交换但是在变量a。不在数组的实际值中。因为你的另一个交换参数是数组的值,它取值变量a。这就是为什么你没有得到理想的输出。 auto a:v的声明实际上是声明,如下所示:

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

等等。 正如你所看到的那样,只有数组值的副本没有引用。这就是你获得这种输出的原因。