And*_*dyG 29 c++ algorithm stl vector c++11
在整个网络上,我看到人们使用擦除/删除习惯用于C++向量,如下所示:
#include <vector> // the general-purpose vector container
#include <iostream>
#include <algorithm> // remove and remove_if
int main()
{
// initialises a vector that holds the numbers from 0-9.
std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
// removes all elements with the value 5
v.erase( std::remove( v.begin(), v.end(), 5 ), v.end() );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
也就是说,如果我想要擦除符合某些条件的所有元素(例如,来自int
s 向量的数字5 ),那么我使用std::remove
或std::remove_if
结合使用vector.erase
如下:
vector.erase( std::remove( vector.begin(), vector.end(), <some_value>), vector.end());
Run Code Online (Sandbox Code Playgroud)
这一般很好用; std::remove
(和remove_if
)将复制(或使用C++ 11中的移动语义)要删除的元素到向量的末尾,因此我们上一个示例中的向量现在将如下所示:
{0,1,2,3,4,6,7,8,9,5 };
元素5加粗,因为它已被移动到最后.
现在,std::remove
将返回一个迭代器,然后我们用它erase
来清除元素.尼斯.
int main()
{
// initialises an empty vector.
std::vector<int> v = {};
// removes all elements with the value 5
v.erase( std::remove( v.begin(), v.end(), 5 ), v.end() );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这似乎在我运行它的所有平台上按预期工作(不擦除任何东西,而不是segfaulting等),但我知道只是因为某些东西工作,并不意味着它不是未定义的行为.
快速参考的vector.erase
说,这(重点煤矿):
iterator erase (const_iterator first, const_iterator last);
Run Code Online (Sandbox Code Playgroud)
first, last
是
指定要移除的向量中的范围的迭代器:
[first,last)
.即,范围包括first
and 之间的所有元素last
,包括由first指向的元素而不是指向的元素last
.成员类型iterator
,const_iterator
是指向元素的随机访问迭代器类型.
vector.erase(vector.end(),vector.end())
不确定的行为?以下是关于异常安全的快速参考说明:
如果删除的元素包含容器中的最后一个元素,则不会抛出异常(无抛出保证).否则,保证容器以有效状态结束(基本保证).无效
position
或range
导致未定义的行为.
所以,答案,至少在我看来是"是",而这个StackOverflow答案似乎支持它.
假设它是未定义的行为,那么任何调用都remove
可以返回一个迭代器,vector.end()
在调用之前应该检查它vector.erase
,并且在空向量上调用remove似乎返回vector.end
:( IDEOne代码如下)
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
vector<int> myInts;
auto anIter = std::remove(myInts.begin(),myInts.end(),5);
if (anIter == myInts.end())
std::cout << "iterator = myInts.end()";
}
Run Code Online (Sandbox Code Playgroud)
实际的删除/删除成语应该是这样的吗?
auto endOfRangeIterator = std::remove(vector.begin(), vector.end(), <value>);
if (endOfRangeIterator != vector.end())
vector.erase(endOfRangeIterator, vector.end())
Run Code Online (Sandbox Code Playgroud)
Igo*_*nik 28
24.2.1/7大多数在数据结构上运行的库的算法模板都有使用范围的接口.范围是一对指定计算开始和结束的迭代器. 范围
[i,i)
是空的范围 ; 通常,范围[i,j)
是指数据结构中的元素,以指向的元素开头,i
但最多但不包括指向的元素j
.
强调我的.
此外,erase
您引用的描述不是标准中的规范性文本.标准就是这样说的(表100):
a.erase(q1,q2)
效果:删除[q1,q2]范围内的元素.
这不需要q1
可解除引用.如果[q1,q2)是空范围(每24.2.1/7),则该范围内没有元素,因此不会删除任何元素.
我认为你的引用更重要的是:
指定要移除的向量中的范围的迭代器:[first,last).即,范围包括第一个和最后一个之间的所有元素,包括第一个指向的元素,但不包括最后指向的元素.成员类型iterator和const_iterator是指向元素的随机访问迭代器类型.
正如我们在评论中发现的那样,来自cpluspluc.com的引用不正确.这不会违反规则,( v.end, v.end)
但如果是,则不正确
#include <vector>
int main()
{
std::vector<int> v = { 1, 2, 3 };
v.erase( v.begin(), v.begin());
}
Run Code Online (Sandbox Code Playgroud)
因为与之相矛盾的陈述
范围包括(...),包括 v.begin()指向的元素,但不包括 v.begin()指向的元素.
不能是一个有效的声明.
第 23.2.2 节中的 C++标准n3337 序列容器要求表100指定了
a.erase(q1,q2)
回报iterator
.请注意:
要求:对于vector和deque,T应为MoveAssignable.效果: 删除[q1,q2]范围内的元素.
而这也正是它说有关范围的[i,j)
在§ 24.2.1/7迭代器的要求
在数据结构上运行的大多数库的算法模板都具有使用范围的接口.范围是一对指定计算开始和结束的迭代器.范围[i,i]是空范围; 通常,范围[i,j]是指 数据结构中的元素,以 i 指向的元素开始,但不包括j指向的元素.当且仅当j可从i到达时,Range [i,j]才有效.将库中的函数应用于无效范围的结果是未定义的.
从而回答你的问题
但是下面的例子怎么样?
cplusplus.com在这种情况下是错误的
那么vector.erase(vector.end(),vector.end())是不确定的行为?
不,不会触发任何未定义的行为.
因此,常见的成语是错误的吗?
不,这是对的.
实际的删除/删除成语应该是这样的吗?
没有必要,虽然它也没关系.