std :: vector :: erase()擦除了错误的元素

时间:2014-05-12 00:29:05

标签: c++ opencv stl std stdvector

所以我在向量中搜索一个元素,我将它存储在一个迭代器中,然后在其上调用erase()。不幸的是,当我设置断点并检查发生了什么时,我发现即使closestObjectIt指向正确的元素,该元素仍然保留在向量中,其他一些元素也会被删除。我不知道这里有什么问题;为什么没有删除正确的迭代器?

我的项目中也有一些从std::vectorcv::vector(来自OpenCV)的隐式转换,反之亦然,但是我将它们排除在外,并且是可疑的。

DetectedObject Head:: findTheClosestObjectFromObjects(std::vector<DetectedObject>& objects)
{
  float minDistance = 10000;
  std::vector<DetectedObject>::iterator closestObjectIt;
  DetectedObject closestObject = objects[0];

  for(std::vector<DetectedObject>::iterator it = objects.begin(); it != objects.end(); ++it)
  {
    float distance = computeDistance2((*it));
    if (distance < minDistance)
    {
        minDistance = distance;
        closestObject = (*it);
        closestObjectIt = it;
    }
  }
  std::cout << "Before erease: " << std::endl;
  objects.erase(closestObjectIt);
  std::cout << "After erease: " << std::endl;

  return closestObject;
}

2 个答案:

答案 0 :(得分:3)

上面的代码看起来不错,您是否尝试过查看DetectedObject的复制赋值运算符?擦除元素时,这就是使用(在c ++ 03中)移动向量中的其他元素,因此这里的错误将使erase正常运行。

答案 1 :(得分:0)

vector :: erase(it)不会删除其指向的元素。它调用复制管理对象的分配,以将其指向的元素分配给下一个对象。此步骤也将在下一个步骤中执行,并继续直到到达end元素为止,这实际上将删除end元素的内存。 因此,请记住为Class编写副本赋值运算符,该运算符将在vector中进行管理,并将与delete()方法一起使用。解决此问题的第二种方法是使用Pointer的std :: vector。

#include <iostream>
#include <vector>
using namespace std;


class BarcodeTagging {
    int value_;
    public:
    BarcodeTagging(int value) : value_(value) {
    }

    ~BarcodeTagging() {
        std::cout << "Delete " << this << "\n";
    }

    const BarcodeTagging& operator=(const BarcodeTagging& other) {
        std::cout << "Call to this \n";
        std::cout << "who calling: " << this << "\n";
        std::cout << "who is called: " << &other << "\n";
        value_ = other.value_;
        return *this;
    }

    int GetValue() const {
        return value_;
    }

};

int main() {
    // your code goes here
    std::vector<BarcodeTagging> taggings;
    BarcodeTagging tag1(1);
    BarcodeTagging tag2(2);
    BarcodeTagging tag3(3);
    taggings.push_back(tag1);
    taggings.push_back(tag2);
    taggings.push_back(tag3);

    std::cout << "Before erase \n";
    for (int i = 0; i < taggings.size(); ++i) {
        std::cout << "element " << i << ": " << &(taggings[i]) << ", with value: " << 
        taggings[i].GetValue() << "\n";
    }
    taggings.erase(taggings.begin());
    std::cout << "After erase \n";

    for (int i = 0; i < taggings.size(); ++i) {
        std::cout << "element " << i << ": " << &(taggings[i]) << ", with value: " << 
        taggings[i].GetValue() << "\n";
    }
    return 0;
}

输出:

Delete 0x55faf3c98c20
Delete 0x55faf3c98c40
Delete 0x55faf3c98c44
Before erase 
element 0: 0x55faf3c98c20, with value: 1
element 1: 0x55faf3c98c24, with value: 2
element 2: 0x55faf3c98c28, with value: 3
Call to this 
who calling: 0x55faf3c98c20
who is called: 0x55faf3c98c24
Call to this 
who calling: 0x55faf3c98c24
who is called: 0x55faf3c98c28
Delete 0x55faf3c98c28
After erase 
element 0: 0x55faf3c98c20, with value: 2
element 1: 0x55faf3c98c24, with value: 3
Delete 0x7ffe1d958b40
Delete 0x7ffe1d958b30
Delete 0x7ffe1d958b20
Delete 0x55faf3c98c20
Delete 0x55faf3c98c24