STL "erase-remove"成语:为什么不"resize-remove"?

STL "erase-remove" idiom: Why not "resize-remove"?

本文关键字:resize-remove 为什么不 成语 erase-remove STL      更新时间:2023-10-16
通常

的理解是从std::vector中完全删除所需项目的好方法是擦除-删除习惯用语。

如上面的链接(截至本文发布之日)中所述,在代码中,擦除删除习惯用语如下所示:

int main()
{
  // initialises a vector that holds the numbers from 0-9.
  std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  // erase-remove idiom to completely eliminate the desired items from the vector
  v.erase( std::remove( std::begin(v), std::end(v), 5 ), std::end(v) ); 
}

我想知道resize-remove成语在功能和性能方面是否等同于erase-remove成语。 或者,也许我错过了一些明显的东西?

以下resize-remove成语等同于上述erase-remove成语吗?

int main()
{
  std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  // Is this "resize-remove" approach equivalent to the "erase-remove" idiom?
  v.resize( std::remove( std::begin(v), std::end(v), 5 ) - v.begin() ); 
}

在我看来,有两个原因:

  1. std::remove算法只需要前向迭代器,但-操作需要随机访问迭代器。

  2. std::remove的结果意味着"容器的新终结"。从逻辑上讲,我们应该抹去["容器的新端","容器的旧端")。

它等效于 std::vector,但不适用于 std::list 或其他容器。不确定 std::list 是否可以减去迭代器,即使可以,这也是一个 O(N) 操作。

它应该没有任何区别; resize的定义是用的inserterase.但通常最好使用标准成语,以便于识别。 和的当然,擦除删除成语适用于任何序列容器,而不仅仅是那些支持 resize . (全部标准容器似乎确实支持resize,但它似乎不是必需的。 所以它可能不可用在用户定义的容器上,即使它们支持所有必需的操作。

在性能方面:resize必须额外执行一项操作测试,以确定它是擦除还是插入,但是我无法想象这会产生重大影响。

我认为erase(first,last)中的erase保证first之前的任何元素都不会被访问或修改,而resize只有在由于调整大小而没有发生重新分配时才保证这一点。

编辑:正如其他人指出的那样,这样的重新分配永远不会发生,所以没有区别