【发布时间】:2013-02-07 10:01:25
【问题描述】:
我有一个向量数组arr,我想从数组向量中搜索并删除其中一个元素具有特定值的向量,称之为elementA。它发生在我身上,如果你看一下数组内部,这样的条件对于连续的几个连续向量是完全满足的。
【问题讨论】:
-
代码中的哪一行没有通过断言?你能出示
arr的声明吗?
标签: c++ stl runtime erase assertion
我有一个向量数组arr,我想从数组向量中搜索并删除其中一个元素具有特定值的向量,称之为elementA。它发生在我身上,如果你看一下数组内部,这样的条件对于连续的几个连续向量是完全满足的。
【问题讨论】:
arr的声明吗?
标签: c++ stl runtime erase assertion
在您的代码中:
int eStart = -1; int eEnd = -1;
for ( int i=0; i<arr.size()-1; i++ )
{
if ( -1 == eStart && arr[i].getElementA() == 0 )
eStart = i;
if ( arr[i].getElementA() == 0 )
eEnd = i;
}
arr.erase( arr.begin()+eStart, arr.begin()+eEnd );
传递给擦除的第二个迭代器必须是您要擦除的最后一个迭代器(只有在找到需要擦除的元素时才调用擦除):
arr.erase( arr.begin()+eStart, arr.begin()+eEnd +1 );
错误:在算术运算期间检查“迭代器范围”:结果必须是 >= 第一个元素,<= 最后一个元素。 begin()-1 不适合:当你不检查是否找到时,即是 eRtart=-1。
_SCL_SECURE_VALIDATE_RANGE(
_Myptr + _Off <= ((_Myvec *)(this->_Getmycont()))->_Mylast &&
_Myptr + _Off >= ((_Myvec *)(this->_Getmycont()))->_Myfirst);
_Myptr += _Off;
注意:不建议从 std::containers 继承。
【讨论】:
std 函数都采用参数“迭代器到范围内的第一个元素”和“迭代器在范围内的最后一个元素”。或者,在数学上,[first, last)。
int eStart = -1; int eEnd = -1;
for ( int i=0; i<arr.size()-1; i++ )
{
if ( -1 == eStart && arr[i].getElementA() == 0 )
eStart = i;
if ( arr[i].getElementA() == 0 )
eEnd = i;
}
if(estart != -1) // added check <---------------------------------
arr.erase( arr.begin()+eStart, arr.begin()+eEnd );
【讨论】:
您可以使用remove-erase idioms 来简化您的代码:
struct IsZeroA
{
IsZeroA() {}
bool operator()(ClassA a)
{
return a.getElementA() == 0;
}
};
arr.erase(std::remove_if(arr.begin(), arr.end(), IsZeroA()), arr.end());
如果您使用 C++11,则使用 lambda
arr.erase(std::remove(arr.begin(), arr.end(),
[](const ClassA& a){ return a.getElementA() == 0; }));
【讨论】:
现在我们不需要审查您的代码,而是提供“通用”解决方案。
我了解您明确希望利用要擦除的元素是连续的这一事实。
我们将使用 @billz 引入的谓词IsZeroA。
auto first=find_if(arr.begin(), arr.end(), IsZero() );
if(first!=arr.end())
{
auto last= find_if_not(first, arr.end(), IsZero() );
arr.erase(first,last);
}
可以简化为:
auto first = find_if (arr.begin(), arr.end(), IsZero() );
arr.erase( first, find_if_not(first, arr.end(), IsZero()) );
【讨论】: