C++ 擦除()向量中的元素不会';行不通
我有一个向量。我需要删除其中的最后3个元素。 描述了这个逻辑。程序崩溃了。可能是什么错误C++ 擦除()向量中的元素不会';行不通,c++,vector,C++,Vector,我有一个向量。我需要删除其中的最后3个元素。 描述了这个逻辑。程序崩溃了。可能是什么错误 vector<float>::iterator d = X.end(); for (size_t i = 1; i < 3; i++) { if (i == 1) X.erase(d); else X.erase(d - i); } vector::迭代器d=X.end(); 对于(大小i=1;i < P> >把端()//> >迭代器传递给
vector<float>::iterator d = X.end();
for (size_t i = 1; i < 3; i++) {
if (i == 1) X.erase(d);
else X.erase(d - i);
}
vector::迭代器d=X.end();
对于(大小i=1;i<3;i++){
如果(i==1)X,则删除(d);
否则X.erase(d-i);
}
这句话
if (i == 1) X.erase(d);
具有未定义的行为
此语句尝试仅删除最后一个元素之前的元素
else X.erase(d - i);
因为你有一个只有两次迭代的循环
for (size_t i = 1; i < 3; i++) {
如果向量中至少有3项,删除最后3项很简单——只需调用3次:
您可以使用
反向迭代器
:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<float> X = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
// start the iterator at the last element
vector<float>::reverse_iterator rit = X.rbegin();
// repeat 3 times
for(size_t i = 0; i < 3; i++)
{
rit++;
X.erase(rit.base());
}
// display all elements in vector X
for(float &e: X)
cout << e << '\n';
return 0;
}
#包括
#包括
使用名称空间std;
int main()
{
向量X={1.1,2.2,3.3,4.4,5.5,6};
//在最后一个元素处启动迭代器
向量::反向迭代器rit=X.rbegin();
//重复3次
对于(大小i=0;i<3;i++)
{
rit++;
X.擦除(rit.base());
}
//以矢量X显示所有元素
用于(浮球和e:X)
coutfrom的end()
定义如下:
返回一个迭代器,该迭代器引用向量容器中结束元素的过去部分。
略低于:
它不指向任何元素,因此不应取消引用。
换句话说,该向量没有end()指向的元素。通过erase()方法取消对该非元素的引用,您可能正在更改不属于该向量的内存。因此,从此以后可能会发生丑陋的事情
通常是用C++约定,将区间描述为[低,高],区间中包含“低”值,间隔中的“高”值<强>排除< /强>。< / P > < P> >把<代码>端()//> >迭代器传递给1-参数超载是不确定的行为。
使位于指定元素处和之后的迭代器无效,使d
在第一次循环迭代后无效
std::vector
有一个2参数erase()
重载,它接受一系列要删除的元素。您根本不需要手动循环:
if(X.size()>=3)
擦除(X.end()-3,X.end());
问题中的一条评论(现已删除)指出“迭代器没有-运算符”。然而,以下代码在MSVC
和clang cl
中编译并工作,标准设置为C++17
或C++14
:
#包括
#包括
int main()
{
std::向量X{1.1f,2.2f,3.3f,4.4f,5.5f,6.6f};
对于(auto f:X)std::cout首先,X.end()
不会将迭代器返回到向量的最后一个元素,而是返回一个迭代器到向量的最后一个元素之后的元素,这是向量实际上不拥有的元素,这就是为什么当您尝试使用X.erase(d)
删除它时程序崩溃的原因
相反,如果向量至少包含3个元素,则可以执行以下操作:
X.erase( X.end() - 3, X.end() );
它将转到最后一个元素的第三个,并删除其后的每个元素,直到到达X.end()
编辑:只是为了澄清,X.end()
是一个指定为具有有效的-
操作的函数,该操作返回另一个LegacyRandomAccessIterator。这里的杀手是d
实际上并不存在。它是一个超过end canary值的函数,只能用于查找向量的结尾。您无法删除它。接下来,只要删除一个迭代器,它就消失了。你不能在事后安全地将它用于任何事情,包括d-i
。我认为它是有效的,因为向量的迭代器是随机访问的,而-
是为这些迭代器类型定义的。@PaulMcKenzie确实是一个clang静态分析器(对标准来说可能非常严格)没有给出任何警告。即使没有为迭代器定义运算符-
,也可以使用or。
#include <vector>
#include <iostream>
int main()
{
std::vector<float> v = { 1, 2, 3, 4, 5 };
for (int i = 0; i < 3 && !v.empty(); ++i)
v.pop_back();
for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';
}
1 2
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<float> X = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
// start the iterator at the last element
vector<float>::reverse_iterator rit = X.rbegin();
// repeat 3 times
for(size_t i = 0; i < 3; i++)
{
rit++;
X.erase(rit.base());
}
// display all elements in vector X
for(float &e: X)
cout << e << '\n';
return 0;
}
X.erase( X.end() - 3, X.end() );