我试图从矢量中删除所有元素。事实上,我写道:
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
为什么打印该程序
#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
答案 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();