English 中文(简体)
迭代地图和删除项目的最佳模式是什么?
原标题:What s the best pattern for iterating over maps of maps and deleting items?

我正在编写一些代码,这些代码基本上可以:

mapSize = map.size();
for(iter=map.begin;iter!=map.end();)
{
  call function which might delete a map item;
  if(map.size()==mapSize )
  {
     iter++;
  }
  else
  {
     mapSize = map.size();
     iter=map.begin(); /* Start again if something was deleted */
  }
}

我认为一定有更好的方法。有什么建议吗?

问题回答

函数应该为您返回下一个有效的迭代器。这就是映射的正常擦除功能的工作原理。

Map具有一个重要特性,即在映射中插入新元素不会使指向现有元素的迭代器失效。从映射中擦除元素也不会使任何迭代器失效,当然,除了实际指向要擦除的元素的迭代器。

编辑

忘记了这个例子

for(iter=map.begin;iter!=map.end();)
{
  map< type >::iterator itCopy( iter++ );

  // call function which might delete a map item;
  foo( itCopy );
}

最好的办法是

  • Only have maps of maps and not maps of pointer to maps
  • Insert objects in them... or shared_ptr

这样,清理将自动为您完成。

首先,调用map.size()可能会花费很多,所以不要使用太多。

for(iter=map.begin;iter!=map.end();)
{
  current_iter = iter;
 ++iter;
  // call function which might delete a map item;
  my_function(current_iter);
}

我对你的代码有一点考虑。如果你从函数的角度来看待它,我认为你应该重写它,不要使用实际的循环,而是使用一个算法函数,比如remove_If,执行多少次就执行多少次,以处理/删除所有需要的元素。我认为这将导致代码更加清晰,而不必处理for循环的显式初始化。例如,在纯C++中(不是lambda,也不是C++0x,这会使这更容易):

template <typename I>
class Processor
{
    bool operator(I const& i)
    { // process, return true if it has to be removed
    }
};

然后,在您的代码中:

std::remove_if(map.begin(), map.end(), Processor<Item_type>());

并且在没有移除任何元素时有某种标志可以发现,这样您就可以继续(可能是Processor类的元素)。

I m not too sure what the question is: the title speaks of "maps of maps", but I don t see any in the example code.

Other than that: what should occur if an item was deleted by the function? Do you want to restart the iteration from the start, or continue where you left off (knowing that where you left off might have been removed from the map)? For the first, your code is basically correct, and I don t think that there s a better solution; at least I can t think of one off hand. For the second, I think you d want something like:

iter = map.begin();
while ( iter != map.end() ) {
    key = iter->first;
    //  call function...
    iter = map.upper_bound( key );
}

This is probably the simplest solution. map.upper_bound is O(lg n), however; if the map is large, this could be a problem. Depending on the implementation of map (and the frequency with which your function removes elements), using ++ on the iterator if nothing has been removed from the map might be faster.

Of course, if you can guarantee that the function in question never deletes the element after the one you re at, you can increment the iterator before calling the function. The solution with upper_bound, however, works unconditionally, regardless of what the function changes in the map.

需要知道的一件好事是,带前缀的运算符++返回迭代器的上一个值(副本),并将当前迭代器提升到下一个值。因此,在您的案例中,下一个代码非常有趣:

for (iter = map.begin(); iter != map.end(); )
{
  // call function which might delete the item
  your_function(++iter);

  // and... that s all !
}

这样,如果您通过<code>erase</code>falvor在函数中移除参数中的迭代器,则当前迭代器不会因移除而无效,并且您是安全的。





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签