【问题标题】:iterator for std::map that allows modification of values, but not insertion/deletionstd::map 的迭代器,允许修改值,但不允许插入/删除
【发布时间】:2014-01-31 05:57:31
【问题描述】:

我对 std::map 迭代器行为有疑问。如果我理解正确, std::map::const_iterator 不允许更改容器中的任何内容,但 std::map::iterator 允许同时更改 it->second 值 和键集(即在迭代时添加/删除元素等)。在我的情况下,我需要允许更改值,但不允许更改键集。 IE。我需要这样的东西:

std::map<int,int>::iterator it=m.begin()
while(it!=m.end())
{
    ++it->second;  // OK: modifying of values is allowed
    if(it->second==1000)
       m.erase(it++); // Error: modifying the container itself is not allowed
    else
       ++it;
}

似乎标准迭代器不区分更改值和更改容器结构。有没有办法通过实现自定义迭代器来施加这种限制?

【问题讨论】:

  • 我认为erase 仅取决于地图实例的常量,而不取决于迭代器。
  • 你试过让容器保持不变吗?但那你又如何给它增加价值呢?
  • 问题是我无法从常量容器中获取非常量迭代器。至于您的问题,可以在一个函数中向地图添加值并在另一个函数中迭代它们。这不是问题,在许多用例中通常会发生这种情况。
  • but std::map::iterator allows to both change the it-&gt;second values and the key set 不,你可能永远不会这样做。密钥始终是不可变的。
  • “如果我理解正确,std::map::const_iterator 不允许更改容器中的任何内容”——这在 C++11 中已更改,const_iterator 现在可以与 @ 一起使用987654326@。原则是,由于您需要对容器的非 const 引用来执行此操作,因此对迭代器的 const-ness 进行狡辩是没有意义的。此外,C++03 接口阻碍了一些完全合理的代码(将 const 引用传递给不修改容器本身但返回迭代器的函数,然后使用该迭代器擦除某些内容)。

标签: c++ map iterator constants


【解决方案1】:

要修改结构(即插入或删除元素),您需要访问底层容器的实例,而不仅仅是迭代器。

因此,您可以通过让有问题的代码仅访问迭代器而不是底层容器来实现您的要求。

template <class Iter> 
cant_remove_if(Iter it, Iter end) { 
    while (it != end) {
        ++it->second; // no problem
        if (it->second==1000)
            // no way to even express the concept `m.erase(it++)` here
        else
            ++begin;
    }
}

【讨论】:

  • 这是一个有趣的解决方案,谢谢!将代码转换成迭代器对语义并不难,这里的好处是显而易见的。
  • 或者也许给代码一个迭代器和一个const对集合的引用,如果由于某种原因它需要一个位置和查找的能力(但不能修改) 其他值。您不能提供的(除了将某种包装器传递给地图)是查找和修改值的能力,但不能通过插入/擦除来修改结构。
猜你喜欢
  • 2011-07-24
  • 2011-01-18
  • 1970-01-01
  • 2012-03-13
  • 2012-06-20
  • 2018-11-16
  • 1970-01-01
  • 2021-09-30
  • 2016-02-12
相关资源
最近更新 更多