13

众所周知,从 a 中完全删除所需项目的一个好方法std::vector擦除删除习语

如上述链接中所述(截至本文发布之日),在代码中,erase-remove习惯用法如下所示:

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() ); 
}
4

4 回答 4

11

在我看来,有两个原因:

  1. std::removealgorithm 只需要 Forward Iterator,但-op 需要 Random Access Iterator。

  2. 结果的std::remove意思是“容器的新端”。从逻辑上讲,我们应该删除 ["the new end of container" , "the old end of container" )。

于 2014-04-04T10:41:52.107 回答
6

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

于 2014-04-04T10:43:03.683 回答
2

它不应该有任何区别;是根据和resize定义的。但通常最好使用标准成语,以便于识别。当然,erase-remove 习惯用法适用于任何序列容器,而不仅仅是那些支持. (所有标准容器似乎都支持,但这似乎不是必需的。因此它可能不适用于用户定义的容器,即使它们支持所有必需的操作。)inserteraseresizeresize

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

于 2014-04-04T10:45:50.310 回答
1

我认为保证之前没有元素被访问或修改,而仅erase在由于调整大小而没有发生重新分配时才保证这一点。erase(first,last)firstresize

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

于 2014-04-04T10:34:08.313 回答