我想就以下问题征询您的意见。
我们有一类叫做“房间”的房间。每个房间可能包含零个或多个“Person”类的实例,因此该Room存储了Person(例如vector)的集合。它拥有。但是,有一些耗时的逻辑与在各个房间之间移动Person有关,因此Person也包含它们所在的当前Room。这只是一个指针,没有所有权。该信息在理论上是多余的,因为可以从房间中的“人”集合中获取该信息,但是如果假设房间数量>>人数众多,则此操作将很慢...
class Room {
std::vector<Person> peopleInside;
};
class Person {
Room* currentRoom; //could be shared_ptr to avoid raw pointers
};
自然,它更复杂(类不止于此),但我已尽可能地简化了它。
我的问题是:
1)在这种情况下,这本身就是循环依赖吗?
2)这个解决方案对您而言是否肮脏/模糊?
3)是否值得更改为其他内容?
最佳答案
这个问题确实需要根据上下文进行研究。如果Person
仅在Room
的上下文中存在,则后向指针是安全的。当Room
被销毁时,Person
也被销毁(轰!),因此不会出错。
但是我怀疑这太简单了。 Room
的声明更有可能是这样的:
class Room {
std::vector<std::shared_ptr<Person>> peopleInside;
};
现在我们有一个可能的“悬空指针”问题,您无法用
std::shared_pointer<Room>
中的Person
解决,因为那样的话您确实具有循环依赖关系,而且shared_ptr
都无法删除其管理的对象(因为Room
包含对Person
的引用,反之亦然,因此是死锁)。因此,改为这样声明
Person
:class Person {
std::weak_ptr<Room> currentRoom;
};
然后从存在的
currentRoom
中初始化shared_ptr<Room>
,使其保持可用。这打破了循环依赖。要取消引用
Room
,您可以执行以下操作:if (auto room_I_am_currently_in = currentRoom.lock())
{
room_I_am_currently_in->OpenDoor ();
}
如果原始的
currentRoom
被销毁,那么shared_ptr<Room>
将失败。当lock
超出范围时(实际上是room_I_am_currently_in
),将释放该锁。要将人转移到另一个房间,只需重新分配
shared_ptr<Room>
即可。有关
currentRoom
的更多信息,请访问cppreference。关于c++ - 具有 “contains”和 “is in”关系的循环依赖,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50665301/