【问题标题】:std::vector::erase() erases the wrong elementstd::vector::erase() 擦除错误的元素
【发布时间】:2014-05-12 00:29:05
【问题描述】:

所以我在向量中搜索一个元素,将它存储在一个迭代器中,并在其上调用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;
}

【问题讨论】:

  • 试试 objects.erase(object.begin() + mostobjectIt)
  • 如果您使用空向量调用它,则会出现未定义的行为,因为objects[0]。除此之外,似乎还不错。尝试实际生成一些输出以确认怀疑;调试器信息可能会产生误导或错误。最好发布一个显示问题发生的最小但完整的程序。
  • 由于您没有使用指针向量,因此值得检查 DetectedObject 的复制赋值运算符。
  • 使用std::find_if 而不是那个循环。
  • @MaximChetrusca 可能表明复制存在问题,正如 Matthew Finlay 所建议的那样 - 可能发布类定义,包括复制构造函数的主体和复制赋值运算符(如果有)

标签: c++ opencv stl std stdvector


【解决方案1】:

上面的代码看起来不错,你有没有试过查看DetectedObject的复制赋值运算符?当你擦除一个元素时,这是用来(在 c++03 中)移动向量中的其他元素的,所以这里的错误将停止 erase 正常运行。

【讨论】:

    【解决方案2】:

    vector::erase(it) 不会删除它指向的元素。它调用托管对象的复制分配以将其指向的元素分配给下一个。这一步也是为下一步做的,一直持续到结束元素,它会真正删除结束元素的内存。 因此,请记住为 Class 编写复制赋值运算符,该运算符将在向量中进行管理,并将与 erase() 方法一起使用。解决这个问题的第二种方法是使用指针的 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-31
      • 1970-01-01
      • 2022-10-24
      • 2011-09-30
      • 2015-01-04
      • 2018-01-27
      • 1970-01-01
      相关资源
      最近更新 更多