为什么根据副本修改源结构?

时间:2016-04-06 16:27:44

标签: c++ struct

所以我得到了以下格式的谜题:

1 2 3 
4 x 5 
6 7 8

在这个函数中,我移动'x',产生4种可能的变化,每种变化都与其中一个邻居有'x'交换位置。

问题是:每当我修改其中一个副本时,原始结构也会被修改,因此下一个变体会累积前一个x。 在函数结束时,current是:

1 x 3 
x 7 x 
6 x 8

(第一个变化实际上是正确的,这就是中间'x'消失的原因)

我的代码:

struct state{
    char** puzzle;
    // (...) 
    bool valid;
    int xi; // x's row
    int xj; // x's column
};

void next_states(state current, state next[4]){
    next[0] = current;
    next[1] = current;
    next[2] = current;
    next[3] = current;

    if(current.xj-1>=0){ // moves 'x' left
        next[0].puzzle[current.xi][current.xj] = current.puzzle[current.xi][current.xj-1];
        next[0].puzzle[current.xi][current.xj-1] = 'x';
        --next[0].xj;
    } else {
        next[0].valid = false;
    }

    if(current.xj+1<3){ // moves 'x' right
        next[1].puzzle[current.xi][current.xj] = current.puzzle[current.xi][current.xj+1];
        next[1].puzzle[current.xi][current.xj+1] = 'x';
        ++next[1].xj;
    } else {
        next[1].valid = false;
    }
    if(current.xi-1>=0){
        next[2].puzzle[current.xi][current.xj] = current.puzzle[current.xi-1][current.xj];
        next[2].puzzle[current.xi-1][current.xj] = 'x';
        --next[2].xi;
    } else {
        next[2].valid = false;
    }
    if(current.xi+1<3){ // moves 'x'down
        next[3].puzzle[current.xi][current.xj] = current.puzzle[current.xi+1][current.xj];
        next[3].puzzle[current.xi+1][current.xj] = 'x';
        ++next[3].xi;
    } else {
        next[3].valid = false;
    }

    print(current.puzzle); // ERROR: accumulating all the changes above
}

1 个答案:

答案 0 :(得分:3)

问题与您char** puzzle的成员struct有关。

您正在state内复制next[4],这有意义,但struct包含指针对象。

这意味着,如果没有正确的copy constructorpuzzle的值将被复制到创建的所有state,从而共享指向同一内存的相同指针。

这显然不是您所需要的,但由于您使用的是固定大小的数组,为什么不使用更合适的值,而不会通过值正确复制,而不会共享任何内容,例如std::array

struct state {
  std::array<std::array<char, 3>, 3> puzzle;
  ...
}