【问题标题】:Erasing and modifying elements in Boost MultiIndex Container在 Boost MultiIndex Container 中擦除和修改元素
【发布时间】:2010-04-16 16:32:14
【问题描述】:

我正在尝试在我的模拟中使用 Boost MultiIndex 容器。我对 C++ 语法的了解非常薄弱,我担心我没有正确地从容器中删除元素或从内存中删除它。我还需要修改元素,我也希望在这里确认语法和基本理念。

// main.cpp
...
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/tokenizer.hpp>
#include <boost/shared_ptr.hpp>
...
#include "Host.h" // class Host, all members private, using get fxns to access

using boost::multi_index_container;
using namespace boost::multi_index;

typedef multi_index_container<
  boost::shared_ptr< Host >,
  indexed_by< 
    hashed_unique< const_mem_fun<Host,int,&Host::getID> >
    //   ordered_non_unique< BOOST_MULTI_INDEX_MEM_FUN(Host,int,&Host::getAge) >
    > // end indexed_by
  > HostContainer;

typedef HostContainer::nth_index<0>::type HostsByID;

int main() {
   ...
   HostContainer allHosts;
   Host * newHostPtr;
   newHostPtr = new Host( t, DOB, idCtr, 0, currentEvents );
   allHosts.insert( boost::shared_ptr<Host>(newHostPtr) );
   // allHosts gets filled up

   int randomHostID = 4;
   int newAge = 50;
   modifyHost( randomHostID, allHosts, newAge );
   killHost( randomHostID, allHosts );
}

void killHost( int id, HostContainer & hmap ){
  HostsByID::iterator it = hmap.find( id );
  cout << "Found host id " << (*it)->getID() << "Attempting to kill. hmap.size() before is " << hmap.size() << " and ";
  hmap.erase( it ); // Is this really erasing (freeing from mem) the underlying Host object?
  cout << hmap.size() << " after." << endl;
}

void modifyHost( int id, HostContainer & hmap, int newAge ){
  HostsByID::iterator it = hmap.find( id );
  (*it) -> setAge( newAge ); // Not actually the "modify" function for MultiIndex...
}

我的问题是

  1. 在shared_ptrs 到Host 对象的MultiIndex 容器allHosts 中,对对象的shared_ptr 的迭代器调用allHosts.erase( it ) 是否足以永久删除该对象并将其从内存中释放?它似乎正在从容器中删除 shared_ptr。
  2. allhosts 容器当前有一个依赖于主机 ID 的有效索引。如果我引入一个调用成员函数 (Host::getAge()) 的有序第二个索引,其中年龄在模拟过程中发生变化,那么当我引用它时,索引是否总是会更新?
  3. 使用 MultiIndex 的 modify 来修改底层对象的年龄与我上面展示的方法有什么区别?
  4. 我对 MultiIndex 中假定/要求保持不变的内容感到模糊。

提前致谢。


更新

根据我在相关 Boost example 中看到的内容,这是我尝试使 modify 语法正常工作的尝试。

struct update_age {
  update_age():(){} // have no idea what this really does... elicits error
  void operator() (boost::shared_ptr<Host> ptr) {
    ptr->incrementAge(); // incrementAge() is a member function of class Host
  }
};

然后在modifyHost 中,我将拥有hmap.modify(it,update_age)。即使奇迹发生了,这证明是正确的,我也希望能对正在发生的事情进行某种解释。

【问题讨论】:

    标签: c++ boost


    【解决方案1】:

    shared_ptr 将在其析构函数中删除实际的Host 对象(如果没有shared_ptr 的其他实例)。 MultiIndex 中的所有对象都被认为是常量。要修改对象,您应该使用 MultiIndex 的方法modify。在这种情况下,索引将在必要时进行更新。

    您可以使用以下仿函数来更改age 字段:

      struct change_age
      {
        change_age(int age) : age_(age) {}    
        void operator()(boost::shared_ptr<Host> h) // shared_ptr !!!
        {
          h->age = age_;
        }
    
      private:
        int age_;
      };
    

    然后按如下方式使用:

      testHosts.modify( it, Host::change_age( 22 ) ); // set age to 22
    

    【讨论】:

    • 再次感谢。即使在研究了您的链接之后,我仍然无法使用修改语法。将 hmap.modify(it,incrementAge()) 与 Host::incrementAge() 一起使用会导致超出范围的错误。我看到一些使用结构的示例(当容器元素是对象本身时)但无法理解为什么我的代码不起作用。
    • 谢谢,Kirill——这非常有用。 (我还有其他接受输入的成员函数,我需要使用 modify() 来调用它们。)当我只是试图调用一个不接受输入的成员函数时,我仍然对该怎么做感到困惑,不过——我上面的编辑代码对吗?
    • 您应该将仿函数对象传递给modify 函数。在你的情况下,它看起来像hmap.modify( it, update_age() )
    • 我上面提出的结构产生以下编译器错误:“main.cpp:76: error: anachronistic old-style base class initializer main.cpp:76: error: unnamed initializer for 'update_age',没有基类”
    • 我注释掉了愚蠢的行 (update_age():(){} ),一切看起来都在工作!
    猜你喜欢
    • 2019-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 1970-01-01
    相关资源
    最近更新 更多