C++ 防止在执行成员函数时删除共享_ptr拥有的对象
我有两节课。为了便于说明,我使用了菜单和菜单项的概念C++ 防止在执行成员函数时删除共享_ptr拥有的对象,c++,c++11,shared-ptr,C++,C++11,Shared Ptr,我有两节课。为了便于说明,我使用了菜单和菜单项的概念 class Menu { public: ... RemoveItem(Item* item) { // Remove appropriate item from menu_items vector }; private: std::vector<std::shared_ptr<Item>> menu_items; } class Item { public: Item(Menu*
class Menu {
public:
...
RemoveItem(Item* item) {
// Remove appropriate item from menu_items vector
};
private:
std::vector<std::shared_ptr<Item>> menu_items;
}
class Item {
public:
Item(Menu* owner) : menu{owner} {}
~Item() { RemoveThisMenuItem() }
void RemoveThisMenuItem() {
for (const auto& ingredient : ingredients) {
ingredient.SetNecessary(false);
}
menu.RemoveItem(this);
}
...
private:
Menu* menu;
std::vector<Ingredients*> ingredients;
...
}
类菜单{
公众:
...
移除项目(项目*项目){
//从菜单项向量中删除相应的项
};
私人:
std::矢量菜单项;
}
类项目{
公众:
项目(菜单*所有者):菜单{owner}{}
~Item(){RemoveThisMenuItem()}
void RemoveThisMenuItem(){
用于(const auto&配料:配料){
成分。必要时设置(假);
}
menu.removietem(这个);
}
...
私人:
菜单*菜单;
std::载体成分;
...
}
本质上,我有一个class项
,它属于class菜单
(可能在其他地方引用了共享的ptr
s)。现在,我想删除一个项目。删除项目时,它需要先执行一些其他功能(如标记所有不必要的成分),然后将其从菜单中删除
现在的实现方式是,当我们想要删除项时,会出现一个奇怪的循环,因为调用项::RemoveThisMenuItem()
调用菜单中的一个函数,该函数删除指向项的智能指针,该指针调用析构函数~item()
,然后调用项::RemoveThisMenuItem()
。解决这个问题的最佳方法是什么?再复制一份拥有该物品的共享\u ptr
,当该物品超出范围时会将其销毁
i、 e.而不是做:
menu_items[n]->RemoveThisMenuItem();
做:
现在当RemoveThisMenuItem()
从向量中删除元素时,它不是共享项的所有权的最后一个对象,因此它不会被销毁,直到owner
超出范围。我会将方法void removietem(Item*Item)
更改为std::shared\u ptr removietem(Item*Item)
并以将相应的项目共享ptr移出向量并返回的方式实现;如果该项已被删除,则返回一个空的共享ptr以避免无休止的递归。通过这种方式,您可以防止removietem
局部删除Item对象(如果上次共享的\u ptr被销毁),并将主题委托给removietem的调用者。然后,调用方可以决定是否保持这样一个共享的_指针(以及相应的对象)处于活动状态
例如:
void RemoveThisMenuItem() {
for (const auto& ingredient : ingredients) {
ingredient.SetNecessary(false);
}
auto ptr = menu.RemoveItem(this);
// at that point, "this" will have not been destroyed;
// when the method is left, however, ptr will be destroyed and the destructor will be called;
}
如果正在执行Item::~Item
,则该项必须已从菜单中删除。否则,它仍然会有一个共享的\u ptr
,并且不会被销毁。如果您正在销毁一个项目
,而该项目仍然有一个共享的\u ptr
,则代码中的其他地方存在设计错误。请用完整的示例说明您的问题。尚不清楚如何在向量被销毁时尝试从向量中删除某些内容。RemoveThisMenuItem
正在从析构函数的上下文中调用。析构函数已在运行。如果有一个std::shared_ptr
要复制,析构函数将不会首先运行。呃,我没有看到这一点。是的,那么设计有问题。
void RemoveThisMenuItem() {
for (const auto& ingredient : ingredients) {
ingredient.SetNecessary(false);
}
auto ptr = menu.RemoveItem(this);
// at that point, "this" will have not been destroyed;
// when the method is left, however, ptr will be destroyed and the destructor will be called;
}