与“包含”和“在”的关系的循环依赖

时间:2018-06-03 10:16:50

标签: c++ architecture software-design

我想收集一下您对以下问题的意见。

我们有一个名为“Room”的课程。每个房间可能包含零个或多个类“Person”的实例,因此Room存储一组Persons(例如vector)。 拥有他们。但是,有一些耗时的逻辑与在房间之间移动人员有关,因此人员还包含他们所在的当前房间。它只是一个没有所有权的指针。这个信息在理论上是多余的,因为可以从房间中人员的集合中得出它,但假设大量的房间>>人数,这样的行动会很慢......

class Room {
std::vector<Person> peopleInside;
};

class Person {
Room* currentRoom; //could be shared_ptr to avoid raw pointers
};

当然,它更复杂(类比这更多)但我尽可能地简化了它。

我的问题是:

1)在这种情况下,这本身就是循环依赖吗?

2)这个解决方案对你来说是不是很脏/不优雅吗?

3)值得改变别的吗?

1 个答案:

答案 0 :(得分:0)

这个问题需要在上下文中进行研究。如果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。这打破了循环依赖。

要取消引用currentRoom,您可以执行以下操作:

if (auto room_I_am_currently_in = currentRoom.lock())
{
    room_I_am_currently_in->OpenDoor ();
}

如果原始shared_ptr<Room>已被破坏,则lock将失败。当room_I_am_currently_in超出范围时(实际上是shared_ptr<Room>),锁定将被释放。

要将一个人搬到另一个房间,只需重新分配currentRoom

有关cppreferencestd::weak_ptr的更多信息。