交换和重新计算给出不同的结果

时间:2012-03-28 20:59:10

标签: c++ swap

我不确定我做错了什么,但应该给出相同结果的两个版本的代码会给出不同的结果。如果有人能解释发生了什么,我真的很感激。

情况如下。我正在使用数组作为'向量',我有一个简单的函数sub,有两个重载来计算两个向量之间的差异。第一个基本上计算v := v - w,而第二个计算x := v - w

// Subtract w[] from v[]
template <class T>
void sub(T *v, T *w, short m)
{
    for (short r = 0; r < m; r++)
        v[r] = v[r] - w[r];
}

// Subtract w[] from v[] and store result in x[]
template <class T>
void sub(T *v, T *w, T *x, short m)
{
    for (short r = 0; r < m; r++)
        x[r] = v[r] - w[r];
}

现在在某些时候我需要计算v - w,如果它满足某些条件,请将v替换为v - w。如果不是,v应保持不变。起初我有

...
// temp := v - w
sub<T>(v, w, temp, m);
if (condition on temp)
{
    // v := v - w
    sub<T>(v, w, m);
}
...

为了提高效率,我认为计算同样的东西两次是浪费,所以我用

替换了上面的内容
...
// temp := v - w
sub<T>(v, w, temp, m);
if (condition on temp)
{
    // swap v and temp
    std::swap(v, temp);
}
...

变量temp实际上在之后重复使用,这可能会导致问题,但每次我再次使用sub<T>(v, w, temp, m);之前先调用temp(从而删除数组中的所有内容)。

现在进行上述替换后,我的算法结果突然改变了。如果有人能解释为什么结果会发生变化以及发生了什么,我将非常感激!

提前致谢。


修改

快速检查显示,在两种情况下,在每次迭代中,v的最终值和temp的初始值相同。所以功能正在做他们应该做的事情......

我能想到解释奇怪行为的唯一可能性是,由于某种原因,函数std::swap使用随机性,导致不同的结果。我为每次运行使用相同的种子,每次都应该得到相同的结果,但如果std::swap在某处使用rand(),那将解释不同的结果。但我不知道为什么这个函数会使用rand()

2 个答案:

答案 0 :(得分:0)

如果您每次要使用temp时将v-w重新计算为temp,则值会有所不同,v未更改且v时{} 1}}指向temp先前指向的数组。

考虑一下:在第一种情况下,您的计算每次都是temp=v-w。在第二种情况下:temp=v-w; swap(temp, v); temp=v-w; - 交换后的那个与前一个不同,因为v指向的数组现在包含来自temp-w的值(使用指针的值)交换后)。也就是说,第二个赋值相当于使用原始数组的temp=(v-w)-w;

答案 1 :(得分:0)

事实证明,在代码中的那一点,“损坏已经完成”。交换是在函数bla内完成的,函数v作为参数,如下所示

void bla(..., T* v, ...)
{
    ...
    // temp := v - w
    sub<T>(v, w, temp, m);
    if (condition on temp)
    {
        // swap v and temp
        std::swap(v, w, m);
    }
    ...
}

但今天我学会了这种方式,函数bla只生成指针的本地副本并使用它,而不是使用实际地址和实际指针存储在记忆。因此,我没有使用v交换全局temp,而是使用v交换本地temp,因此这不会影响全局v。这也解释了为什么我没有注意到本地的任何问题,因为在函数内部,v确实表现得如此。因此,在代码中的那一点,交换值的唯一方法是重新计算表达式。

一个简单的解决方案:将函数声明更改为void bla(..., T*& v, ...),以便函数v中使用的bla的本地副本实际上对应于与全局相同的物理内存地址v。然后std::swap()工作正常。