提问人:HarrisonO 提问时间:10/9/2023 更新时间:10/9/2023 访问量:52
递归回溯 C++、内存地址更改、损坏指针
Recursive Backtracking C++, Memory address changing, damaging pointers
问:
我目前正在研究一种用于迷宫生成的递归回溯方法。目前,我正在努力从函数中获取正确的值。在函数中,它返回正确的坐标,但是,当在另一个函数中引用它们时,这些点不再有效并且包含不正确的值。GetNeighbours()
RecursiveBacktracking()
我一直在尝试调试它很长一段时间,但似乎无法弄清楚。
任何关于为什么会这样解释的解释都将非常有帮助!
塔克斯
#include <vector>
#include <cstdlib>
#include <stdlib.h>
#include <algorithm>
#include <ctime>
#include <random>
#include <stack>
class Node{
public:
std::vector<Node*> GetNeighbours(Node* baseNode, std::vector<std::vector<Node>> mazeVector){
std::vector<Node*> neighbours;
//Get south neighbour
if(baseNode->ypos + 1 < mazeVector.size()){
if(!mazeVector.at(baseNode->ypos+1).at(baseNode->xpos).isVisited){
neighbours.push_back(&mazeVector.at(baseNode->ypos+1).at(baseNode->xpos));
}
}
//Get north neighbour
if(baseNode->ypos - 1 >= 0){
if(!mazeVector.at(baseNode->ypos-1).at(baseNode->xpos).isVisited){
neighbours.push_back(&mazeVector.at(baseNode->ypos-1).at(baseNode->xpos));
// std::cout << neighbours[0]->ypos << ", " << neighbours[0]->xpos;
}
}
//Get east neighbour
if(baseNode->xpos + 1 < mazeVector.at(baseNode->ypos).size()){
if(!mazeVector.at(baseNode->ypos).at(baseNode->xpos+1).isVisited){
neighbours.push_back(&mazeVector.at(baseNode->ypos).at(baseNode->xpos+1));
// std::cout << neighbours[0]->ypos << ", " << neighbours[0]->xpos;
}
}
if(baseNode->xpos -1 >= 0){
if(!mazeVector.at(baseNode->ypos).at(baseNode->xpos-1).isVisited){
neighbours.push_back(&mazeVector.at(baseNode->ypos).at(baseNode->xpos-1));
//std::cout << neighbours[0]->ypos << ", " << neighbours[0]->xpos;
}
}
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(neighbours.begin(), neighbours.end(), g);
// for(int i = 0; i < neighbours.size(); i++){
// std::cout << "Neighbours[" << i << "] before return = (" << neighbours[i]->ypos << ", " << neighbours[i]->xpos << ")" << std::endl;
// std::cout << "Memory Address [" << i << "] within function = " << neighbours[i] << std::endl;
// std::cout << "Memory Address [" << i << "]within maze = " << &mazeVector[neighbours[i]->ypos][neighbours[i]->xpos] << std::endl;
// }
return neighbours;
}
bool isVisited = false;
int ypos;
int xpos;
/* Node(int y, int x, bool visited = false){
this->ypos = y;
this-> xpos = x;
this-> isVisited = visited;
}
*/
};
void PrintMaze(std::vector<std::vector<Node>>& mazeVector){
for(int i = 0; i < mazeVector.size(); i++){
for (int j = 0; j < mazeVector[i].size(); j++)
{
Node* currentNode = &mazeVector.at(i).at(j);
if(currentNode->isVisited){
std::cout << 'X';
}else{
std::cout << '.';
}
// std::cout << ¤tNode <<" = (" << currentNode->ypos << ", " << currentNode->xpos <<")";
// std::cout << currentNode.GetNeighbours(currentNode, i, j, mazeVector).size();
}
std::cout<<std::endl;
}
}
void RecursiveBacktracking(std::vector<std::vector<Node>>& maze, int x, int y){
_sleep(500);
std::cout<<"------GENERATING------" << std::endl;
std::vector<Node*> stack;
stack.emplace_back(&maze[0][0]);
Node* currentNode = stack[0];
currentNode->isVisited = true;
while(stack.size() > 0){
_sleep(3000);
PrintMaze(maze);
currentNode->isVisited = true;
std::vector<Node*> neighbours = currentNode->GetNeighbours(currentNode, maze);
PrintMaze(maze);
// for(int i = 0; i < neighbours.size(); i++){
// std::cout << "Neighbours[" << i << "] after return = (" << neighbours[i]->ypos << ", " << neighbours[i]->xpos << ")" << std::endl;
// std::cout << "Neighbours[" << i << "] Memory after return = (" << neighbours[i] << std::endl;
// }
if(neighbours.size() > 0){
stack.emplace_back(neighbours[0]);
std::cout << "Selected neighbour = (" << stack[stack.size()-1]->ypos << ", " << stack[stack.size()-1]->xpos << ")" << std::endl;
//std::cout<< "Selected Neighbour Coords: " << currentNode-> ypos<< ", " << currentNode-> xpos<< std::endl;
currentNode = stack[stack.size()-1];
}else{
stack.pop_back();
currentNode = stack[stack.size()-1];
}
for (size_t i = 0; i < stack.size(); i++)
{
/* code */
}
std::cout<< "Size while in loop: "<<stack.size() << std::endl;
}
std::cout<<stack.size() << std::endl;
}
int main(){
int length;
int width;
std::cout << "Please enter and length and width: " << std::endl;
std::cin >> length >> width;
std::cout << "Please enter a seed for maze generation or enter '0' for a random seed: " << std::endl;
int seed;
std::cin >> seed;
if(seed == 0){
std::srand((unsigned) time(NULL));
}else{
std::srand(seed);
}
std::vector<std::vector<Node>> mazeVector(length, std::vector<Node>(width));
for(int i = 0; i < length; i++){
for (int j = 0; j < width; j++)
{
Node currentNode;/* = Node(i, j); */
currentNode.ypos = i;
currentNode.xpos = j;
mazeVector.at(i).at(j) = currentNode;
}
}
PrintMaze(mazeVector);
RecursiveBacktracking(mazeVector, 0, 0);
return 1;
}
答:
3赞
PaulMcKenzie
10/9/2023
#1
这是按值传递的,这意味着这是一个本地副本。mazeVector
std::vector<std::vector<Node>> mazeVector
然后在函数本身中,您正在执行以下操作:
neighbours.push_back(&mazeVector.at(baseNode->ypos).at(baseNode->xpos+1));
您正在将 的临时地址存储在 中,然后最终返回 。当函数返回时,neighbors
neighbors
return neighbours;
这将被销毁,因此所有这些地址都不再有效。mazeVector
您应该通过引用而不是按值传递:mazeVector
std::vector<Node*> GetNeighbours(Node* baseNode, std::vector<std::vector<Node>>& mazeVector)
但即使这样,也不能保证你的代码能正常工作。原因是您不应该存储矢量元素的地址。如果向量的大小超出容量,因此必须重新分配内部向量存储器怎么办?您存储的所有这些指针现在都将失效。
评论
1赞
PaulMcKenzie
10/9/2023
更改了措辞。
下一个:返回对多态对象的引用
评论
std::vector<std::vector<Node>> mazeVector
-- 您是否知道您正在按值传递它,这意味着该函数正在处理本地副本?当函数返回时,该副本会发生什么情况?main
&