Question

So I search for an element in a vector, I store it in an iterator and I call the erase() on it. Unfortunately, when I set the breakpoints and check what's happening, I see that even if the closestObjectIt points to the right element, that element still remains in the vector, some other element being deleted. I have no clue what is wrong here; why the right iterator is not deleted?

I also had in my project some implicit conversions from std::vector to cv::vector (from OpenCV) and vice-versa, but I eliminated them, being suspicious.

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;
}
Was it helpful?

Solution

The code above looks good, have you tried looking at DetectedObject's copy-assignment operator? When you erase an element, this is what's used (in c++03) to move the other elements in the vector, so an error here will stop erase operating properly.

OTHER TIPS

vector::erase(it) doesn't remove the element pointed by it. It calls to copy assignment of managed object to assign the element pointed by it with the next one. This step is done for the next one too, and continue until it reach the end element and it will really delete the memory of end element. So, remember to write copy assignment operator for Class that will be managed in vector and will be used with erase() method. The second ways to overcome this issue is use std::vector of Pointer.

#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;
}

And the output:

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top