Answers:
首先,X.end()
不将迭代器返回到向量的最后一个元素,而是将迭代器返回到向量的最后一个元素之后的元素,这是向量实际上不拥有的元素,这就是为什么当您尝试X.erase(d)
程序崩溃时将其擦除。
而是,如果向量包含至少3个元素,则可以执行以下操作:
X.erase( X.end() - 3, X.end() );
而是转到最后的第三个元素,并擦除此后的每个元素,直到到达为止X.end()
。
编辑:只是为了澄清,X.end()
是LegacyRandomAccessIterator,它被指定为具有有效-
操作,该操作返回另一个LegacyRandomAccessIterator。
end()
from cppreference的定义是:
返回引用向量容器中的past-the-end元素的迭代器。
并在下面:
它没有指向任何元素,因此不应取消引用。
换句话说,向量没有end()指向的元素。通过使用delete()方法取消引用该非元素,您可能正在更改不属于该向量的内存。因此,丑陋的事情可能从那里发生。
按照通常的C ++惯例,将间隔描述为[low,high],其中“ low”值包含在间隔中,而“ high”值不包含在间隔中。
您可以使用reverse_iterator
:
#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;
}
有几件事要提到:
reverse_iterator rit
从的最后一个元素开始vector X
。此职位称为rbegin
。erase
需要经典iterator
才能使用。我们可以rit
通过致电获得base
。但是,新的迭代器将rit
向前指向下一个元素。rit
打电话之前base
和erase
另外,如果您想了解更多信息reverse_iterator
,建议您访问此答案。
问题中的注释(现已删除)指出“没有-迭代器的运算符”。但是,以下代码在和中都可以编译和工作,MSVC
并且clang-cl
标准设置为C++17
或C++14
:
#include <iostream>
#include <vector>
int main()
{
std::vector<float> X{ 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f };
for (auto f : X) std::cout << f << ' '; std::cout << std::endl;
std::vector<float>::iterator d = X.end();
X.erase(d - 3, d); // This strongly suggest that there IS a "-" operator for a vector iterator!
for (auto f : X) std::cout << f << ' '; std::cout << std::endl;
return 0;
}
为提供的定义operator-
如下(在<vector>
标题中):
_NODISCARD _Vector_iterator operator-(const difference_type _Off) const {
_Vector_iterator _Tmp = *this;
return _Tmp -= _Off;
}
但是,我当然不是C ++语言律师,这可能是那些“危险的” Microsoft扩展之一。我很想知道这是否可以在其他平台/编译器上使用。
-
是针对这些类型的迭代器定义的。
这个说法
if (i == 1) X.erase(d);
具有未定义的行为。
并且此语句尝试仅删除最后一个元素之前的元素
else X.erase(d - i);
因为您只有两个迭代的循环
for (size_t i = 1; i < 3; i++) {
您需要类似以下内容的东西。
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main()
{
std::vector<float> v = { 1, 2, 3, 4, 5 };
auto n = std::min<decltype( v.size() )>( v.size(), 3 );
if ( n ) v.erase( std::prev( std::end( v ), n ), std::end( v ) );
for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';
return 0;
}
程序输出为
1 2
d
没有杀手really。这是仅可用于找到末尾的金丝雀值vector
。您无法删除它。接下来,一旦删除迭代器,它就消失了。之后,您将无法安全地将其用于任何事物,包括d - i
。