我想收集一下您对以下问题的意见。
我们有一个名为“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)值得改变别的吗?
答案 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
。
有关cppreference的std::weak_ptr
的更多信息。