我有三节课:房间,门和世界
#include <set>;
using namespace std;
class Door; // Forward declaration
class Room {
public:
Door* door1;
Door* door2;
Room(){}
~Room() {
delete door1;
door1 = 0;
delete door2;
door2 = 0;
}
};
class Door {
public:
Room* roomA;
Room* roomB;
Door(Room* roomA, Room* roomB) {
this->roomA = roomA;
this->roomB = roomB;
linkRooms(); // This sets up the Door-Pointers in the Rooms
// so they know about the new door.
}
~Door() {
// Returns the room-owned pointer pointing at this door
getMyRoomPointer(roomA) = 0;
getMyRoomPointer(roomB) = 0;
}
Door * & getMyRoomPointer(Room * const & room) {
if (room->door1 == this) return room->door1;
else return room->door2;
}
void linkRooms() {
roomA->door1 = this;
roomB->door2 = this;
}
};
class World {
public:
std::set<Room*> rooms;
World() {
// Set up two rooms and link them using a door
Room* newRoom = new Room();
rooms.insert(newRoom);
Room* anotherNewRoom = new Room();
rooms.insert(anotherNewRoom);
new Door(newRoom, anotherNewRoom);
}
~World() {
// Iterate over the rooms and call delete on all of them
for (std::set<Room*>::iterator it = rooms.begin(); it != rooms.end(); ++it) {
delete *it;
}
}
};
int main() {
World world;
return 0;
}
在运行main时,构造函数仅用两个房间和一个门作为它们之间的链接来填充整个世界。主要返回后,应删除世界,并应注意所有房间和门。
事实是,我的Door析构函数从未被调用过。因此,房间内的“门”指针未设置为null,而“另一侧”的房间试图删除同一扇门时出现错误。
当我只创建Door的实例,然后立即删除它时,我没有遇到任何问题:
int main(){
Room oneRoom;
Room anotherRoom;
Door* door = new Door(&oneRoom, &anotherRoom);
delete door; // works just fine
return 0;
}
问题:为什么不调用Door构造函数?是否可以像第一个示例一样设置“门”?
我知道,我要双重删除房间的门指针,并且可以(并且应该)使用SmartPointers。现在,我只是想知道为什么我要面对这种行为。毕竟,我还是C ++的新手。
我现在确实设置了一个可运行的示例,该示例再现了该错误。
您delete
在Door
定义之前致电。因此,程序的行为是不确定的,并且不能保证调用析构函数。
标准(草稿)[expr.delete]的引号:
- 如果要删除的对象在删除时具有不完整的类类型,并且完整的类具有非平凡的析构函数或释放函数,则该行为是不确定的。
解决方案:如果类型的析构函数很重要(例如,用户定义的,例如~Door
,那么在类型完成之前切勿删除此类对象)。在这种情况下,请Door
在调用delete的函数之前定义。
通常,除非类类型完整,否则永远不能调用成员函数。不幸的是,在使用析构函数的情况下,编译器可能并不总是能够捕获该错误。PS。g ++确实会警告您的程序:warning: possible problem detected in invocation of delete operator: [-Wdelete-incomplete]
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句