循环语句中指针赋值出错
最近在写人工智能作业的时候遇到了一点问题,就是在循环语句中对指针类型赋值出现错误,导致所有的结点的前驱指针最终指向自身。
问题描述
以下使用一个简单的示例来模拟当时出现的问题。
MyStruct 为一个自定义结构体类型,包含数据成员 val 和前驱结点 pre。首先将初始结点(0,nullptr)
加入队列 Q,随后在每次循环中,用变量 fs 接收队列 Q 的队首元素并将其出队,并根据该结点生成一个新结点,该新结点 val = fs.val + 1
,且将其前驱结点设为 fs 并加入到队列 Q 中。直到 fs.val >= 5
时退出循环。
struct MyStruct
{
int val;
MyStruct* pre;
MyStruct(int v = 0, MyStruct* p = nullptr) : val(v), pre(p) {}
};
int main()
{
std::queue<MyStruct> Q;
Q.emplace(0, nullptr);
MyStruct target;
while (!Q.empty()) {
MyStruct fs = Q.front();
Q.pop();
if (fs.val >= 5) {
target = fs;
break;
}
Q.emplace(fs.val + 1, &fs);
}
std::cin.get();
}
如果代码运行如我们预期,最终将会得到一个 val 为 5 的结点,并且其前驱为一个 val 为 4 的结点,以此类推,形成一个 val 从 5 到 0 的链表。但事实上,最终结点之间并没有彼此相连,结点 target 的 pre 为自身。
问题原因
如果仔细观察,变量 fs 在整个循环过程中都占用同一片内存空间,而子节点的前驱结点 pre 直接指定为了 fs 的地址,那么如果 fs 的值遭到改变,即该地址的数据被改变,那么结点的前驱结点 pre 也会被改变。即下次循环执行 MyStruct fs = Q.front();
后结点的前驱结点就遭到了改变,且指向了自身。
解放方法
由于 fs 的始终占用一片内存空间,为了防止因 fs 的数据被改变而使得结点前驱结点数据遭到改变,可以为结点的前驱结点重新开辟一片内存空间并赋予当前 fs 的数据。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Lordaeron_ESZ's blog!
评论