2017-07-02 54 views
1

假设我有一个容器一样如下:修剪连续STD容器

std::vector<int> numbers{1,2,3,4,5,6,7,8}; 

什么是“修剪”,它最有效的方法是什么?如在中,从其中删除元素,但仅从开始或结束。

可以说我想将'数字'转换为容器{3,4,5,6,7}。一种方法我能想到的删除“8”非常有效地为:

numbers.resize(numbers.size()-2); 

这似乎保证无重新分配和去除不适合新尺寸所有尾随元素(在这种情况下,只有最后一个元素,8)。

有没有类似的方式来做到这一点与容器的开始?而且,只要我传递给resize的参数小于或等于容器的原始大小,该操作是否保证为O(1)?

+2

从'std :: vector'的开头(或不是结尾的任何地方)删除元素需要复制剩余/后续元素。 'numbers.resize(numbers.size() - 2);'会移除最后2个元素,而不仅仅是最后一个元素(尽管从后面移除元素不需要任何复制,所以这并不比'擦除元素。)。为什么你需要“修剪”矢量? – UnholySheep

+0

如果你需要在开始或结束时进行有效的插入/删除操作,那么试试'std :: deque'。 – StoryTeller

回答

2

一种方法我能想到的删除“8”非常有效地为:

numbers.resize(numbers.size()-2); 

假设这应该是-1,不,这不是你想要做什么。您应该始终选择用于该作业的工具。在这种情况下,如果你想只删除最后一个元素,那就是:

numbers.pop_back(); 

如果你想删除最后n元素(假设n <= numbers.size()全境),这就是:

numbers.erase(numbers.end() - n, numbers.end()); 

这保证了没有重新分配或额外移动 - 它只会调用适当的析构函数,然后移动结束指针。如果这种类型可以被破坏,那么即使是这个类型的第一部分也是不可操作的。

如果你想删除第一n元素,这就是对称:

numbers.erase(numbers.begin(), numbers.begin() + n); 

然而,这涉及整体平移以后的元素来填补这个洞 - 所以它有多少元素的功能在那边。 vector从后面抹去很便宜,但从前面擦除很昂贵(这本身就是具有pop_back()但不是pop_front()的动机)。正因为如此,如果你想trim(),从右边擦掉。

如果你从前面进行大量擦除,你应该考虑使用一个容易修剪两端的容器 - 如std::deque。好的是 - 代码看起来都一样。您仍然希望使用双迭代器erase()进行修剪。

你绝对想要做的是(尽管多么诱人它可能会出现):

numbers.assign(numbers.begin() + 2, numbers.end() - 1); 

也就是不确定的行为。

4

std::vector不支持从有效地将前除去的元素,但boost::circular_buffer确实:http://www.boost.org/doc/libs/release/doc/html/circular_buffer.html

在一定程度上,std::deque支持此过,但它有一些问题,如常见的实现仅在分配少量这意味着它可能比circular_buffer分配更多的内存。并且从std::deque中删除很多元素的速度并不快,因为它必须释放许多块(而circular_buffer只是递增整数值)。