-2

我想将当前对象的指针传递给新创建的相同类型的对象。我像这样尝试过,但不知何故新对象 prev 字段指向自身。我正在使用 Microsoft Visual C++ 编译器。

Class A{

    A *prev;

    A(A* a)
    {
        prev = a;
    }
    vector<A> addToVector()
    {
        vector<A> res;
        res.push_back(A(this));
        return res;
    }

};

现在,当我从向量中获取结果并将其添加到队列中时,指针指向自身而不是其前身。出了什么问题?

- - 编辑

这是我将新状态添加到向量并返回它们的代码片段

const int dim = 3;

int goal[] = {1,2,3,4,5,6,7,8,0};

class State{
public:
vector<int> board;
const State *prev;
int g;
int h() const{
    int res = 0;
    for(int i=0; i<dim*dim; i++){
        if(goal[i] != board[i]) res++;
        }
    return res;
    }
inline bool operator==(const State &other) const{
    bool eq = true;
    for(int i=0; eq && i<dim*dim; i++){
        eq = board[i] == other.board[i];
        }
    return eq;
    }

inline bool operator<(const State& other) const{
    return g + h() > other.g + other.h();
    }
inline State& operator=(const State& other){
    this->board = other.board;
    this->g = other.g;
    this->prev = other.prev;
    assert(this != prev);
    return *this;
    }
State(int a[], int b, const State *p){
    board.assign(a, a+dim*dim);
    g = b;
    prev = p;
    assert(prev != this);
    }
bool isSolution(){
    bool isSol = true;
    for(int i=0; i<dim*dim && isSol; i++){
        isSol = board[i] == goal[i];
        }
    return isSol;
}

vector<State> getSuccessors(){
    vector<State> successors;
    // find zero
    bool found = false;
    int z_pos;
    for(int i=0; i<dim*dim && !found; i++){
        found = board[i] == 0;
        if(found) z_pos = i; 
        }
    switch(z_pos){
    case 0:
        {
        // 1st row left
        int n1[] = {board[1], 0, board[2], board[3],board[4],board[5],board[6],board[7],board[8]};
        // 1st columnn up
        int n2[] = {board[3], board[1], board[2], 0,board[4],board[5],board[6],board[7],board[8]};
        State s1(n1, g+1, this);
        State s2(n2, g+1, this);
        successors.push_back(s1);
        successors.push_back(s2);
        } break;
    case 1:
        {
        // 1st row left
        int n1[] = {board[0], board[2], 0, board[3],board[4],board[5],board[6],board[7],board[8]};
        // 1st row right
        int n2[] = {0, board[0], board[2], board[3],board[4],board[5],board[6],board[7],board[8]};
        // 2nd column up
        int n3[] = {board[0], board[4], board[2], board[3],0,board[5],board[6],board[7],board[8]};
        State s1 (n1, g+1, this);
        State s2 (n2, g+1, this);
        State s3 (n3, g+1, this);
        successors.push_back(s1);
        successors.push_back(s2);
        successors.push_back(s3);
        } break;
    case 2:
        {
        // 1st row right
        int n1[] = {board[0], 0, board[1], board[3],board[4],board[5],board[6],board[7],board[8]};
        // 3rd column up
        int n2[] = {board[0], board[1], board[5], board[3],board[4],0,board[6],board[7],board[8]};
        State s1(n1, g+1, this);
        State s2(n2, g+1, this);
        successors.push_back(s1);
        successors.push_back(s2);
        } break;
    case 3:
        {
        // 1st column up
        int n1[] = {board[0], board[1], board[2], board[6],board[4],board[5],0,board[7],board[8]};
        // 1st column down
        int n2[] = {0, board[1], board[2], board[0],board[4],board[5],board[6],board[7],board[8]};
        // row 2 left
        int n3[] = {board[0], board[1], board[2], board[4],0,board[5],board[6],board[7],board[8]};
        State s1(n1, g+1, this);
        State s2(n2, g+1, this);
        State s3(n3, g+1, this);
        successors.push_back(s1);
        successors.push_back(s2);
        successors.push_back(s3);
        } break;
    case 4:
        {
        // row 2 right
        int n1[] = {board[0], board[1], board[2], 0,board[3],board[5],board[6],board[7],board[8]};
        // row 2 left
        int n2[] = {board[0], board[1], board[2], board[3],board[5],0,board[6],board[7],board[8]};
        // column 2 up
        int n3[] = {board[0], board[1], board[2], board[3],board[7],board[5],board[6],0,board[8]};
        // column 2 down
        int n4[] = {board[0], 0, board[2], board[3],board[1],board[5],board[6],board[7],board[8]};
        State s1(n1, g+1, this);
        State s2(n2, g+1, this);
        State s3(n3, g+1, this);
        State s4(n4, g+1, this);
        successors.push_back(s1);
        successors.push_back(s2);
        successors.push_back(s3);
        successors.push_back(s4);
        } break;
    case 5:
        {
        // row 2 right
        int n1[] = {board[0], board[1], board[2], board[3],0,board[4],board[6],board[7],board[8]};
        // column 3 up
        int n2[] = {board[0], board[1], board[2], board[3],board[4],board[8],board[6],board[7],0};
        // column 3 down
        int n3[] = {board[0], board[1], 0, board[3],board[4],board[2],board[6],board[7],board[8]};
        State s1(n1, g+1, this);
        State s2(n2, g+1, this);
        State s3(n3, g+1, this);
        successors.push_back(s1);
        successors.push_back(s2);
        successors.push_back(s3);
        } break;
    case 6:
        {
        // row 3 left
        int n1[] = {board[0], board[1], board[2], board[3],board[4],board[5],board[7],0,board[8]};
        // column 1 down
        int n2[] = {board[0], board[1], board[2], 0,board[4],board[5],board[3],board[7],board[8]};
        State s1(n1, g+1, this);
        State s2(n2, g+1, this);
        successors.push_back(s1);
        successors.push_back(s2);
        } break;
    case 7:
        {
        // row 3 right
        int n1[] = {board[0], board[1], board[2], board[3],board[4],board[5],0,board[6],board[8]};
        // row 3 left
        int n2[] = {board[0], board[1], board[2], board[3],board[4],board[5],board[6],board[8],0};
        // column 2 down
        int n3[] = {board[0], board[1], board[2], board[3],0,board[5],board[6],board[4],board[8]};
        State s1(n1, g+1, this);
        State s2(n2, g+1, this);
        State s3(n3, g+1, this);
        successors.push_back(s1);
        successors.push_back(s2);
        successors.push_back(s3);
        } break;
    case 8:
        {
        // row 3 right
        int n1[] = {board[0], board[1], board[2], board[3],board[4],board[5],board[6],0,board[7]};
        // column 3 down
        int n2[] = {board[0], board[1], board[2], board[3],board[4],0,board[6],board[7],board[5]};
        State s1(n1, g+1, this);
        State s2(n2, g+1, this);
        successors.push_back(s1);
        successors.push_back(s2);
        } break;
    }
    return successors;
}

void getPath(){
    assert(prev == this);
    cin.get();
    }

};


void solve(){
priority_queue<State> openSet;
set< vector<int> > closedSet;
int init[] = {1,0,3,4,2,6,7,5,8};
State initial(init,0,NULL);
openSet.push(initial);
while(!openSet.empty()){
    State n = openSet.top();
    assert(&n != n.prev); //FAILS
    openSet.pop();
    if(n.isSolution()){
        cout << "openSet size:   " << openSet.size() << endl;
        cout << "closedSet size: " << closedSet.size() << endl;
        n.getPath();
        break;
        }
    else if(closedSet.find(n.board) != closedSet.end()){
        ; // skip
        }
    else{
        closedSet.insert(n.board);
        vector<State> successors = n.getSuccessors();
        for(int i=0; i<successors.size(); i++){
            if(closedSet.find(successors[i].board) == closedSet.end()) openSet.push(successors[i]);
        }
    }
}
}

int main(){
//freopen("packrec.in", "r", stdin);
//freopen("packrec.out", "w", stdout);
//int t; cin >> t; while(t--)
    solve();
return 0;
}
4

2 回答 2

0

用你建设似乎不可能得到this == this->prev。然而,这个唯一的保持是对象停留足够长的时间。我怀疑他们没有。证明这一点的最简单方法是断言 的值prev

A::A(A* p): prev(p) { assert(this != this->prev); }
A::A(A const& a): prev(a.prev) { assert(this != this->prev); }
A& A::operator= (A const& a) {
    this->prev = a.prev;
    assert(this != this->prev); 
}

我怀疑被引用的原始对象在某个时候消失了,并且该位置被不幸地引用自身的对象重用。您乐意传递对象并保持指向这些对象的指针使其成为可能的候选对象。由于您的代码不完整(而且大多不相关),因此无法重现问题,因此我无法确认这是否确实是问题所在。

于 2012-05-13T02:04:03.103 回答
0

如果不阅读(长)上下文代码,您需要注意不要调用addToVector超出范围的对象。由于直接创建类型的本地对象肯定是非法的A(因为向量可能比它长),所以所有构造函数A::A都应该是私有的(除了vector必须访问的复制构造函数)并且对象应该从工厂函数返回,其中addToVector是一个。

编写一个循环很容易,您打算通过定义一个局部变量来创建一系列链接对象,但是由于本地的地址在循环的每次迭代中都是相同的,所以所有对象看起来都是相同的。这很容易导致自链接。

啊,我addToVector在上下文代码中搜索,它甚至没有使用。所以一般的建议是有效的。顺便说一句,这是在您编辑扩展代码之后。

于 2012-05-13T12:59:19.633 回答