从任意容器中廉价删除元素的惯用方法?
Idiomatic way to cheaply remove an element from an arbitrary container?
所有C++标准库容器都有一个insert()
方法;但它们并不都有remove()
方法,该方法不接受任何参数,而是以任意顺序执行最便宜的删除。现在,当然,对于不同的容器,这将有不同的作用:在向量中,我们将从后面删除,在单个列表中,我们将从前面删除(除非我们保留指向尾部的指针(,等等,根据实现细节。
那么,除了为每个容器滚动我自己的模板专用化之外,还有没有更惯用的方法可以做到这一点?
标准容器设计的一部分是,如果可以为该容器提供最佳操作(通过选定的度量(,则它们仅提供作为成员函数的操作。
如果容器提供成员函数,那是因为有某种方法可以实现该函数,这是该容器的最佳方法。
如果无法提供操作的最佳实现(如remove()
(,则不提供。
只有std::list
和(C++11 及更高版本(std::forward_list
设计用于有效移除元素,这就是为什么它们是唯一具有remove()
构件功能的容器。
其他容器不是为有效去除任意元素而设计的;
std::array
无法调整大小,因此具有insert()
或remove()
成员函数是没有意义的。std::deque
仅在开头或结尾针对移除进行了优化。- 从
std::vector
中移除元素的效率低于其他容器,除了(可能(从末端移除。
因此,为这些容器实现remove()
成员函数违背了设计理念。
因此,如果您希望能够有效地从容器中删除元素,则需要为作业选择合适的容器。
为标准容器滚动自己的包装器来模拟某些容器不支持的操作只是误导 - 从某种意义上说,鼓励包装器类的用户相信,如果他们对性能或内存使用有特殊要求,他们不需要小心选择容器。
所以回答你的问题
"那么,除了为每个容器滚动我自己的模板专用化之外,还有没有更惯用的方法可以做到这一点?
有很多方法可以删除
-
序列容器和无序容器的 erase(( 返回下一个 删除项目之后的迭代器。
-
关联容器的 erase(( 不返回任何内容。
/* *从矢量或德克中删除*/
vector<int> vec = {1, 4, 1, 1, 1, 12, 18, 16}; // To remove all '1'
for (vector<int>::iterator itr = vec.begin(); itr != vec.end(); ++itr) {
if ( *itr == 1 ) {
vec.erase(itr);
}
} // vec: { 4, 12, 18, 16}
// Complexity: O(n*m)
remove(vec.begin(), vec.end(), 1); // O(n)
// vec: {4, 12, 18, 16, ?, ?, ?, ?}
vector<int>::iterator newEnd = remove(vec.begin(), vec.end(), 1); // O(n)
vec.erase(newEnd, vec.end());
// Similarly for algorithm: remove_if() and unique()
// vec still occupy 8 int space: vec.capacity() == 8
vec.shrink_to_fit(); // C++ 11
// Now vec.capacity() == 4
// For C++ 03:
vector<int>(vec).swap(vec); // Release the vacant memory
/* *从列表中删除*/
list<int> mylist = {1, 4, 1, 1, 1, 12, 18, 16};
list<int>::iterator newEnd = remove(mylist.begin(), mylist.end(), 1);
mylist.erase(newEnd, mylist.end());
mylist.remove(1); // faster
/* *从关联容器或无序容器中删除*/
multiset<int> myset = {1, 4, 1, 1, 1, 12, 18, 16};
multiset<int>::iterator newEnd = remove(myset.begin(), myset.end(), 1);
myset.erase(newEnd, myset.end()); // O(n)
myset.erase(1); // O(log(n)) or O(1)
- 数组元素打印的递归方法
- 如何实现 Front() 方法以返回模板化双向链表C++的第一个元素?
- 有什么方法可以将元素添加到列表中,如图所示?
- 在向量中查找大于 0(或通常为 k)的最小元素的最佳方法是什么?
- C++将所有元素从矢量复制到地图/unordered_map的最佳方法
- 在C++中更改结构内部元素的方法?
- 通过作为指向 C++ 函数的指针传递来访问 std::array 元素的正确方法是什么?
- 有没有更快的方法可以在 std::vector 中插入元素
- 返回向量元素的 l 值的正确方法是什么?
- 按升序打印矢量的所有元素直到它为空而没有重复项的最有效方法是什么?
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- 如何在不迭代的情况下对数组中的每个元素调用方法
- 是否有更有效的方法来检查元素是否在给定的区间内
- 这种获取模板参数包中最后一个元素的方法是否有隐藏的开销?
- 将__m256的奇怪元素提取到__m128中的有效(在锐龙上)方法?
- 为什么 memcpy() 是一种将元素添加到 'std::map' 的方法?
- 从长(且合理)稀疏向量中选择随机元素的最有效方法是什么?
- 如何使用返回第 n 个元素的方法创建元组
- 如何在不使用 vector::erase() 的情况下编写自定义 Vector 方法来删除元素?
- 从任意容器中廉价删除元素的惯用方法?