具有“包含"关系的循环依存关系.和“在...中" [英] Circular dependency with the relationships "contains" and "is in"

查看:129
本文介绍了具有“包含"关系的循环依存关系.和“在...中"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想就以下问题征求您的意见.

I would like to gather opinion from you about the following problem.

我们有一个名为房间"的课程.每个房间可能包含零个或多个"Person"类的实例,因此该Room存储了Person(例如vector)的集合.它拥有.但是,有一些与在各个房间之间移动人物相关的耗时逻辑,因此该人物还包含了他们所在的当前房间.它只是一个没有所有权的指针.此信息在理论上是多余的,因为可以从房间中的人"集合中获取信息,但是如果假设房间数量>>人数众多,则此操作将很慢...

We have a class called "Room". Each room may contain zero or more instances of a class "Person", so the Room stores a collection of Persons (e.g. vector). It owns them. However, there is some time-consuming logic related to moving Persons between Rooms, so the Person also contains current Room they are in. It is just a pointer without ownership. This information is theoretically redundant, because one could derive it from the collections of Persons in rooms, but assuming large number of rooms >> number of people, such an operation would be slow...

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

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

自然地,它更复杂(类不止于此),但我已尽可能地简化了它.

Naturally, it is more complex (classes have more than this) but I have simplified it as much as possible.

我的问题是:

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

1) In this situation, is this a circular dependency per se?

2)这个解决方案对您来说是肮脏的吗?

2) Is this solution dirty/inelegant for you?

3)是否值得更改为其他内容?

3) Is it worth changing to something else?

推荐答案

这个问题确实需要根据上下文进行研究.如果Person仅存在于Room的上下文中,则后向指针是安全的.当Room被销毁时,Person也会被销毁(轰!),所以什么都不会出错.

This question needs really to be studied in context. If Persons only exist in the context of a Room then the back-pointer is safe. When a Room is destroyed then the Persons are destroyed too (boom!) so nothing can go wrong.

但是我怀疑这太简单了. Room的声明更有可能是这样的:

But I suspect that's too simplistic. The declaration of Room is more likely to be something like:

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

现在我们有一个可能的悬空指针"问题,您不能使用Person中的std::shared_pointer<Room>来解决,因为这时您 do 具有循环依赖项,而shared_ptr都没有将会能够删除它正在管理的对象(因为Room拥有对Person的引用,反之亦然,因此是死锁).

And now we have a possible 'dangling pointer' problem, which you can't solve with a std::shared_pointer<Room> in Person because then you do have a circular dependency and neither shared_ptr will ever be able to delete the object it is managing (because Room holds a reference to Person and vice versa, so, deadlock).

因此,改为这样声明Person:

class Person {
    std::weak_ptr<Room> currentRoom;
};

然后从Room存在时保持可用的某些shared_ptr<Room>中初始化currentRoom.这打破了循环依赖.

And initialise currentRoom from some shared_ptr<Room> that you keep available while that Room exist. This breaks the circular dependency.

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

To dereference currentRoom, you can then do:

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>)时,该锁将被释放.

And if the original shared_ptr<Room> has been destroed then lock will fail. The lock will be released when room_I_am_currently_in goes out of scope (it's actually a shared_ptr<Room>).

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

And to move a person to another room, just reassign currentRoom.

有关std::weak_ptr的更多信息,请访问 cppreference .

More about std::weak_ptr at cppreference.

这篇关于具有“包含"关系的循环依存关系.和“在...中"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆