Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 防止在执行成员函数时删除共享_ptr拥有的对象_C++_C++11_Shared Ptr - Fatal编程技术网

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; 
}