从矢量中删除

时间:2015-06-10 16:05:16

标签: c++ vector

我试图从矢量中删除所有元素。事实上,我写道:

INSERT INTO Members (startDate)
SELECT sh.startDate
FROM ((SubHistory sh)
INNER JOIN History h ON sh.histId = h.histId)
INNER JOIN Members m on h.memId = m.memId
WHERE sh.type = 46 AND m.memId = Members.memId

DEMO

为什么打印该程序

#include<iostream>
#include<vector>

std::vector<int> foo(std::vector<int> v)
{
    std::vector<int> result;
    std::cout << "Initial size = " << v.size() << std::endl;
    for(int i = 0; i < v.size(); i++)
    {
        std::cout << "Size = " << v.size() << std::endl;
        v.erase(v.begin() + i);
    }
    return result;
}

int main()
{
    int a[] = {1 ,2, 5, 8, 213, 2};
    std::vector<int> v;
    v.assign(a, a+6);
    foo(v);
}

在哪里

Initial size = 6
Size = 6
Size = 5
Size = 4

7 个答案:

答案 0 :(得分:4)

第三次删除后你有i == 3和v.size()== 3并且退出

答案 1 :(得分:3)

您应该学会使用适当的循环来实现您想要达到的目标,或者只是恰当地使用它们。 当您事先知道需要执行多少次迭代时,可以使用for循环,但要小心使用索引。

你在循环中做的是改变向量的大小,所以每次迭代v.size()都会变小。当i == 3时,向量大小已减少到3,循环结束的时间早于预期。

您希望实现的目标有一些替代方案,

// Store the size of the array so it doesn't change midway in the loop
for(int i = 0, iEnd = v.size(); i < iEnd; i++)
{
    std::cout << v.size() << std::endl;
    //v.erase( v.begin() );
    v.pop_back(); // pop_back is quicker but erases from the end
}

或者

// More appropriate, since you don't even need to know the size
while ( !v.empty() ) {
    std::cout << v.size() << std::endl;
    v.pop_back();
}

在这些循环中,我假设您不关心任何特定元素,只想删除它们。如果您关心特定元素,其他答案已经提到过。

但实际上你应该使用

v.clear();

因为STL已经为你做了。

答案 2 :(得分:1)

要从矢量中删除所有元素,请使用std::vector::clear

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    std::vector<int> v(10);
    cout << v.size() << endl;
    v.clear();
    cout << v.size();
    cin.get();
    return 0;
}

答案 3 :(得分:1)

因为在3次删除之后(当大小= 4时),v.size()为3且i为3,所以i < v.size()不再为真且你打破了for循环, for(int i = 0; i < v.size(); i++)并从函数返回。

如果您只想删除矢量的所有元素,请尝试v.clear()

答案 4 :(得分:1)

如果考虑这个抽象循环,您可以轻松理解问题

size_t N = v.size();

size_t i = 0;
size_t j = N;


while ( i < j )
{
   i++;
   j--;
}

因此,您将精确删除向量中的( N + 1 ) / 2个元素,或者更准确地删除( v.size() + 1 ) / 2个元素。:)

要删除矢量中的所有元素,您可以使用成员函数clear()

如果你想有选择地删除矢量的元素,你可以写

for ( auto it = v.begin(); it != v.end(); )
{
    if ( need_to_delete ) it = v.erase( it );
    else ++it;
}

其中need_to_delete是您要使用的任何条件。

答案 5 :(得分:1)

当删除第一个元素时, v.size()也会更新。当它达到大小3时,它的大小也是3,所以它退出for循环。

注意:尽量不要使用更新条件( for loop 的中间条件)作为循环继续更改的内容,除非您确定要这样做。

答案 6 :(得分:1)

您可能知道“迭代器失效”的概念,并且您正在使用size_t i来避免这种情况。不幸的是,你正在使用的是仍然本质上是一个迭代器,从向量中删除一个元素会使所有迭代器失效,而不仅仅是::iterator类型的迭代器:)。 / p>

invalidate是一个精心挑选的术语,具有微妙的细微差别。这意味着迭代器并没有停止工作,有时您可能会发现它们仍在工作。但你不应该相信他们。

所以invalidate并不意味着它们被破坏或错误,这意味着你应该重新考虑它们。例如,如果您已捕获vec.begin()并且已导致向量重定位其数据,则vec.begin()的值可能不再有效。它通常不是,但你已被警告:)

std::vector是在一个简单的连续数组上实现的:

[  0  ][  1  ][  2  ][  3  ]

当你擦除一个元素时,它所包含的对象被破坏,然后右边的所有元素都被移动,在内存中被物理地重新定位。

[  0  ][~~~~~][  2  ][  3  ] sz=4
[  0  ][  2  <<  2  ][  3  ] sz=4
[  0  ][  2  ][  3  <<  3  ] sz=4
[  0  ][  2  ][  3  ][?????] sz=4

然后向量通过删除的元素数减少size,在本例中为1:

[  0  ][  2  ][  3  ] sz=3

当对象不简单或向量很大时,您可以看到erase()的整个过程非常昂贵,但我会回过头来看。

您的实施问题是您增加i,并且尺寸缩小,因此您最终会删除每一个元素。

  i=0
[  0  ][  1  ][  2  ][  3  ] sz=4

erase(i);
  i=0
[~~~~~][  1  ][  2  ][  3  ] sz=3
[  1  <<  1  ][  2  ][  3  ] sz=3
[  1  ][  2  <<  2  ][  3  ] sz=3
[  1  ][  2  ][  3  <<  3  ] sz=3
[  1  ][  2  ][  3  ][?????] sz=3
[  1  ][  2  ][  3  ] sz=3
  i=0

i++;
         i=1
[  1  ][  2  ][  3  ] sz=3

erase(i);
         i=1
[  1  ][~~~~~][  3  ] sz=3
[  1  ][  3  <<  3  ] sz=3
[  1  ][  3  ][?????] sz=3
[  1  ][  3  ] sz=2
         i=1

i++;
               i=2
[  1  ][  3  ] sz=2

break;

std::vector提供clear清空数组,但如果您有兴趣了解如何自行执行此类操作:

选项1:从后面删除

while (!vec.empty())
    vec.pop_back();

这样做会破坏最后一个元素,然后减小大小。这很便宜。

[  0  ][  1  ][  2  ][  3  ] sz=4
pop_back();
[  0  ][  1  ][  2  ][~~~~~] sz=4
[  0  ][  1  ][  2  ] sz=3

选项2:删除一系列元素

std::vector<int> vec { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
vec.erase(vec.begin() + 2, vec.begin() + 5);
vec.erase(vec.begin(), vec.end());

选项3:收缩阵列:

vec.resize(0);

选项4:清除

这是清空矢量

的首选和常规方法
vec.clear();