我想就以下问题征询您的意见。

我们有一类叫做“房间”的房间。每个房间可能包含零个或多个“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/

10-13 02:03