【问题标题】:runtime assertion error while operating on vector c++在向量 C++ 上操作时出现运行时断言错误
【发布时间】:2013-02-07 10:01:25
【问题描述】:

我有一个向量数组arr,我想从数组向量中搜索并删除其中一个元素具有特定值的向量,称之为elementA。它发生在我身上,如果你看一下数组内部,这样的条件对于连续的几个连续向量是完全满足的。

【问题讨论】:

  • 代码中的哪一行没有通过断言?你能出示arr的声明吗?

标签: c++ stl runtime erase assertion


【解决方案1】:

在您的代码中:

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 ); 

错误:在算术运算期间检查“迭代器范围”:结果必须是 &gt;= 第一个元素,&lt;= 最后一个元素。 begin()-1 不适合:当你不检查是否找到时,即是 eRtart=-1

_SCL_SECURE_VALIDATE_RANGE(
        _Myptr + _Off <= ((_Myvec *)(this->_Getmycont()))->_Mylast &&
        _Myptr + _Off >= ((_Myvec *)(this->_Getmycont()))->_Myfirst);
    _Myptr += _Off;

注意:不建议从 std::containers 继承。

【讨论】:

  • 为什么是最后一个? begin() 指向第一个元素,它的索引为 0,所以如果我将 eEnd 添加到 begin() 中,我会得到我认为正确的索引..
  • @eReM 所有采用迭代器范围的std 函数都采用参数“迭代器到范围内的第一个元素”和“迭代器在范围内的最后一个元素”。或者,在数学上,[first, last)
  • 当然,我混合了索引和元素,如果我想指向第 i 个元素,我必须使用第 i-1 个索引。
【解决方案2】:
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 ); 

【讨论】:

    【解决方案3】:

    您可以使用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; }));
    

    【讨论】:

      【解决方案4】:

      现在我们不需要审查您的代码,而是提供“通用”解决方案。

      我了解您明确希望利用要擦除的元素是连续的这一事实。

      我们将使用 @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()) );
      

      【讨论】:

      • @josh130 :这两行(加上 pdefined 谓词)是否解决了问题?
      • 抱歉,我没有收到您的问题通知。你的第一个答案解决了这个问题,谢谢!
      猜你喜欢
      • 1970-01-01
      • 2012-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-02
      • 1970-01-01
      • 2022-08-23
      相关资源
      最近更新 更多