当我将该类放入另一个类的地图中时,类stringvariables将丢失其值

那么问题是,当我把这些类放在TransparentMaze类的地图中时,我的房间类放弃了stringvariables的“名称”值。 我不明白他们去哪里..是与地图比较器或别的东西有关的问题,希望有人可以帮助。

#include <iostream> #include <string> #include <list> #include <map> using namespace std; class Point{ int x; int y; public: Point(int, int); ~Point(){}; int getX() ; int getY() ; }; struct cmp_str { bool operator()(Point p1, Point p2) { if (p1.getY() < p2.getY() || p1.getY() == p2.getY() && p1.getX() < p2.getX()) { return true; } return false; } }; class Room{ Room *north; Room *south; Room *east; Room *west; public: int createDirection[4]; std::string name; Room(std::string); ~Room(); std::string getName(); std::list<std::string> findPathTo(std::string); void fillMap(map<Point, Room*, cmp_str>*, int*, int*); Room& createNorth(std::string); Room& createSouth(std::string); Room& createEast(std::string); Room& createWest(std::string); Room& getNorth(); Room& getSouth(); Room& getEast(); Room& getWest(); Room& get(std::string); Room& get(std::list<std::string>); void setNorth(Room*); void setSouth(Room*); void setEast(Room*); void setWest(Room*); //bool validatePath(std::list<std::string>); }; class Maze{ Room *entry; public: Maze(string); ~Maze(); Room& getEntry(); }; class TransparentMaze{ std::map<Point, Room*, cmp_str> maze; int width; int height; public: TransparentMaze(Maze); ~TransparentMaze(){}; std::map<Point, Room*, cmp_str>& getMaze(); }; TransparentMaze::TransparentMaze(Maze maze) { maze.getEntry().fillMap(&this->maze, &this->width, &this->height); } std::map<Point, Room*, cmp_str>& TransparentMaze::getMaze() { return maze; } Point::Point(int x, int y) { this->x = x; this->y = y; } int Point::getX() { return x; } int Point::getY() { return y; } Maze::Maze(std::string name) { entry = new Room(name); } Maze::~Maze() { delete entry; } Room& Maze::getEntry() { return *entry; } Room::Room(std::string name) { this->name = name; for (int i = 0; i < sizeof(createDirection) / sizeof(int); i++) { createDirection[i] = 0; } north = NULL; south = NULL; east = NULL; west = NULL; } Room::~Room() { for (int i = 0; i < sizeof(createDirection) / sizeof(int); i++) { switch(i) { case 0: if (createDirection[i] == 1) { delete north; } break; case 1: if (createDirection[i] == 1) { delete south; } break; case 2: if (createDirection[i] == 1) { delete east; } break; case 3: if (createDirection[i] == 1) { delete west; } break; } } } Room& Room::get(std::string direction) { switch(direction[0]) { case 'N': case 'n': return (this->north == NULL ? *this : *this->north); case 'S': case 's': return (this->south == NULL ? *this : *this->south); case 'E': case 'e': return (this->east == NULL ? *this : *this->east); case 'W': case 'w': return (this->west == NULL ? *this : *this->west); default: break; } return *this; } Room& Room::get(std::list<std::string> pathList) { std::list<std::string>::iterator it; Room *room = this; for (it = pathList.begin(); it != pathList.end(); it++) { if (&(*room) == &room->get(*it)) { return *this; } room = &room->get(*it); } return *room; } void Room::fillMap(map<Point, Room*, cmp_str> *maze, int *width, int *height) { std::list<std::list<std::string>> listOfLists; std::list<std::list<std::string>>::iterator it1; Room *r; int n, counter; *width = *height = 0; listOfLists.push_back(std::list<std::string>()); for (;;) { counter = 0; for (it1 = listOfLists.begin(); it1 != listOfLists.end(); it1++) { r = &this->get(*it1); //Point p((int)r->getName()[0] - 64, (int)r->getName()[1] - 48); //cout << r->getName() << " " << &*r << " " << &this->get(*it1) << endl; maze->insert(std::make_pair(Point((int)r->getName()[0] - 64, (int)r->getName()[1] - 48), &*r)); //cout << r->getName() << endl; std::string lastRoom; n = 0; if (it1->size() > 0) { lastRoom = *--it1->end(); } if (&r->getNorth() != NULL && lastRoom.compare("S") != 0) { n++; counter++; if (n == 1) { it1->push_back("N"); } else { std::list<std::string> bufferList(it1->begin(), --it1->end()); bufferList.push_back("N"); listOfLists.push_back(bufferList); } } if (&r->getEast() != NULL && lastRoom.compare("W") != 0) { n++; counter++; if (n == 1) { it1->push_back("E"); } else { std::list<std::string> bufferList(it1->begin(), --it1->end()); bufferList.push_back("E"); listOfLists.push_back(bufferList); } } if (&r->getWest() != NULL && lastRoom.compare("E") != 0) { n++; counter++; if (n == 1) { it1->push_back("W"); } else { std::list<std::string> bufferList(it1->begin(), --it1->end()); bufferList.push_back("W"); listOfLists.push_back(bufferList); } } if (&r->getSouth() != NULL && lastRoom.compare("N") != 0) { n++; counter++; if (n == 1) { it1->push_back("S"); } else { std::list<std::string> bufferList(it1->begin(), --it1->end()); bufferList.push_back("S"); listOfLists.push_back(bufferList); } } } if(counter == 0) { /*cout << listOfLists.size() << endl; map<Point, Room*, cmp_str>::iterator it; for (it = maze->begin(); it != maze->end(); it++) { cout << "X: "<< it->first.getX() << " Y: " << it->first.getY() << "; " << (*it->second).getName() << endl; }*/ return; } } } std::list<std::string> Room::findPathTo(std::string roomName) { std::list<std::list<std::string>> listOfLists; std::list<std::list<std::string>>::iterator it1; Room *r; int n, counter; listOfLists.push_back(std::list<std::string>()); for (;;) { counter = 0; for (it1 = listOfLists.begin(); it1 != listOfLists.end(); it1++) { r = &this->get(*it1); std::string lastRoom; n = 0; if (it1->size() > 0) { lastRoom = *--it1->end(); } if (r->getName().compare(roomName) == 0) { return *it1; } if (&r->getNorth() != NULL && lastRoom.compare("S") != 0) { n++; counter++; if (n == 1) { it1->push_back("N"); } else { std::list<std::string> bufferList(it1->begin(), --it1->end()); bufferList.push_back("N"); listOfLists.push_back(bufferList); } } if (&r->getEast() != NULL && lastRoom.compare("W") != 0) { n++; counter++; if (n == 1) { it1->push_back("E"); } else { std::list<std::string> bufferList(it1->begin(), --it1->end()); bufferList.push_back("E"); listOfLists.push_back(bufferList); } } if (&r->getWest() != NULL && lastRoom.compare("E") != 0) { n++; counter++; if (n == 1) { it1->push_back("W"); } else { std::list<std::string> bufferList(it1->begin(), --it1->end()); bufferList.push_back("W"); listOfLists.push_back(bufferList); } } if (&r->getSouth() != NULL && lastRoom.compare("N") != 0) { n++; counter++; if (n == 1) { it1->push_back("S"); } else { std::list<std::string> bufferList(it1->begin(), --it1->end()); bufferList.push_back("S"); listOfLists.push_back(bufferList); } } } if(counter == 0) { return std::list<std::string>(); } } } /*bool Room::validatePath(std::list<std::string> pathList) { std::list<std::string>::iterator it; Room *room = this; for (it = pathList.begin(); it != pathList.end(); it++) { if (&(*room) == &room->get(*it)) { return false; } room = &room->get(*it); } return true; }*/ std::string Room::getName(){ return name; } Room& Room::createNorth(std::string name) { north = new Room(name); createDirection[0] = 1; north->setSouth(this); return *north; } Room& Room::createSouth(std::string name) { south = new Room(name); createDirection[1] = 1; south->setNorth(this); return *south; } Room& Room::createEast(std::string name) { east = new Room(name); createDirection[2] = 1; east->setWest(this); return *east; } Room& Room::createWest(std::string name) { west = new Room(name); createDirection[3] = 1; west->setEast(this); return *west; } Room& Room::getNorth() { return *north; } Room& Room::getSouth() { return *south; } Room& Room::getEast() { return *east; } Room& Room::getWest() { return *west; } void Room::setNorth(Room *room) { north = room; } void Room::setSouth(Room *room) { south = room; } void Room::setEast(Room *room) { east = room; } void Room::setWest(Room *room) { west = room; } int main() { Maze maze("A5"); maze.getEntry().createSouth("A6").createEast("B6").createSouth("B7").createWest("A7") .getEast().createEast("C7").createNorth("C6").createEast("D6").createEast("E6") .getWest().createNorth("D5").createEast("E5").getWest().getSouth().getWest() .createNorth("C5").createWest("B5").createNorth("B4").createWest("A4").createNorth("A3") .getSouth().getEast().getSouth().getEast().createNorth("C4").createNorth("C3") .createWest("B3").getEast().createNorth("C2").createWest("B2").createWest("A2") .createNorth("A1").getSouth().getEast().getEast().createEast("D2").createSouth("D3") .createSouth("D4").createEast("E4").createNorth("E3").createNorth("E2").createNorth("E1") .createWest("D1").createWest("C1").createWest("B1").getEast().getEast().getEast() .createEast("F1").createEast("G1").createEast("H1").createSouth("H2").createEast("I2") .createSouth("I3").createEast("J3").createNorth("J2").createNorth("J1").createWest("I1") .getEast().getSouth().getSouth().getWest().getNorth().getWest().getNorth().getWest() .getWest().getWest().getSouth().getSouth().createEast("F3").createEast("G3") .createNorth("G2").createWest("F2").getEast().getSouth().createEast("H3").createSouth("H4") .createEast("I4").createEast("J4").createSouth("J5").createWest("I5").createWest("H5") .getEast().createSouth("I6").createEast("J6").createSouth("J7").createWest("I7") .createWest("H7").createWest("G7").getEast().createNorth("H6").createWest("G6") .createWest("F6").createNorth("F5").createNorth("F4").createEast("G4").createSouth("G5") .getNorth().getWest().getSouth().getSouth().createSouth("F7").createWest("E7") .createWest("D7"); //cout << (int)'A' << endl; //cout << (int)'1' << endl; /*std::list<std::string> list(maze.getEntry().findPathTo("E7")); std::list<std::string>::iterator it; for (it = list.begin(); it != list.end(); it++) { cout << *it << endl; }*/ //cout << sizeof(maze.getEntry()) << endl; //Here it has still a value.. cout << maze.getEntry().getName().length() << endl; TransparentMaze tMaze(maze); //Here not anymore.. why it's gone? cout << maze.getEntry().getName().length() << endl; //tMaze.getMaze(); /*map<Point, Room*, cmp_str>::iterator it; for (it = tMaze.getMaze().begin(); it != tMaze.getMaze().end(); it++) { cout << "X: "<< it->first.getX() << " Y: " << it->first.getY() << "; " << it->second->name << endl; }*/ } 

这有点复杂,但现在正在发生。 简而言之, TransparentMaze构造函数获取一个通过值传递的Maze实例,但是Maze类不可复制(它包含一个指针)。 解决这个问题最直接的方法就是让Maze不可复制(更多下面),并使TransparentMaze参考MazeMaze& )而不是副本。

 class Maze{ Room *entry; // these two lines make it non-copyable Maze(const Maze&); // <-- private copy constructor Maze& operator=(const Maze&); // <-- private assignment operator public: Maze(string); ~Maze(); Room& getEntry(); }; class TransparentMaze{ std::map<Point, Room*, cmp_str> maze; int width; int height; public: TransparentMaze(Maze&); // pass by reference ~TransparentMaze(){}; std::map<Point, Room*, cmp_str>& getMaze(); }; TransparentMaze::TransparentMaze(Maze& maze) { maze.getEntry().fillMap(&this->maze, &this->width, &this->height); } 

当构造TransparentMaze时,构造函数会得到一个Maze的副本,它会复制entry指针。 当TransparentMaze构造函数完成并且~Maze析构函数删除entry指针时,该副本被删除。 当您尝试稍后使用该删除的entry指针(在原来的maze实例中,它被复制),您将得到未定义的行为(我的系统崩溃了)。

这是很多代码。 这有很多问题,但是实际的问题是这样的 – 你的对象执行浅拷贝,并在破坏时自行清理。 以这种方式使用的浅拷贝将无法正常工作,因为当一个拷贝被销毁时,对象的后续副本中指向的内存将被释放 – 留下剩余对象中的悬挂指针。

 // This function takes a COPY of the Maze object TransparentMaze::TransparentMaze(Maze maze) // But the Maze object cannot be safely copied // because it only does a shallow copy // and destroy's its entry upon destruction Maze::~Maze() { delete entry; } 

考虑将“ Maze和“ Room原始指针移动到智能指针类型,否则将不得不为所有类编写copy-constructors

看到这个问题的深层复制与浅层复制的讨论。