简体   繁体   English

矢量迭代器不是dereferencable

[英]Vector iterator not dereferencable

I have an abstract base class called Shape from which both Circle and Rectangle are derived, but when I execute the following code in VS 2005 I get the error Debug assertion failed. 我有一个名为Shape的抽象基类,从中派生出Circle和Rectangle,但是当我在VS 2005中执行以下代码时,我得到错误Debug assertion failed。 At the same time I have not overloaded == operator in any class 同时我没有在任何类中重载==运算符

Expression:Vector iterator not dereferencable, what is the reason for this. 表达式:向量迭代器不可解除引用,这是什么原因。

  vector<Shape*> s1;
  s1.push_back(new Circle(point(1,2),3));
  s1.push_back(new Circle(point(4,3),5));
  s1.push_back(new Rectangle(point(1,1),4,5));

  vector<Shape*> s2(s1);
  reverse(s1.begin(),s1.end());

  (*find(s1.begin(),s1.end(),new Circle(point(1,2),3)))->move(point(10,20));

Simple : 简单:

  • find fails since your newly created Circle can't be found in the vector with comparing Shape * 查找失败,因为在比较Shape *的向量中找不到新创建的Circle
  • a failed find returns the end iterator which is not deferencable as caught by a Debug assertion 失败的查找返回结束迭代器,它不是由调试断言捕获的可引用的

For it to work like you want, you do need to compare Shape, not Shape* 为了让它像你想要的那样工作,你需要比较Shape,而不是Shape *

As pointed out in other answers, boost::ptr_vector is an easy way to achieve this. 正如其他答案所指出的, boost :: ptr_vector是实现这一目标的简单方法。

Like @David Pierre suggests: find is value-based: it looks in the range of iterators for a pointer (eg 0x0F234420) that equals the pointer to the new Circle(point(1,2),3) you just created. 就像@David Pierre建议的那样:find是基于值的:它在一个指针的迭代器范围内查找(例如0x0F234420),它等于你刚创建的new Circle(point(1,2),3)的指针。 Since that's a new object, it won't be there. 由于这是一个新对象,它不会存在。

You can get around this by using find_if with an operator that compares the objects referenced to by the pointer. 您可以通过使用find_if与运算符来比较指针引用的对象来解决这个问题。

However, the Criterium should be able to differentiate between shape types. 但是,Criterium应该能够区分形状类型。

class Shape {
public:
    //amongst other functions
    virtual bool equal( const Shape* ) const = 0;
};

class Circle : public Shape {
public:
    bool equal( const Shape* pOther ) const {
        const Circle* pOtherCircle = dynamic_cast<const Circle*>( pOther );
        if( pOtherCircle == NULL ) return false;
        // compare circle members
    }
};

class Rectangle : public Shape {
public:
    bool equal( const Shape* pOther ) const {
        const Rectangle* pOtherR = dynamic_cast<const Rectangle*>( pOther );
        if( pOtherR == NULL ) return false;
        // compare rectangle members
    }
};



Shape* pFindThis = new Circle(point(1,2),3);
vector<Shape*>::const_iterator itFound = find_if(s1.begin(),s1.end(), 
    bind1st( mem_fun( &Shape::equal ), pFindThis) ) );
delete pFindThis; //leak resolved by Mark Ransom - tx!

if( itFound != s1.end() ) {
    (*itFound)->move(point(10,20));
}

This is a good reason to use boost::ptr_vector. 这是使用boost :: ptr_vector的一个很好的理由。

It not only handles the fact that your objects need to be destroyed. 它不仅处理您的对象需要被销毁的事实。
xtofl@: You forgot the virtual destructor. xtofl @:你忘记了虚拟析构函数。

But it also makes the members look like objects by returning references rather than pointers. 但它也通过返回引用而不是指针使成员看起来像对象。 This allows you to use the standard algorithms much more naturally rather than playing around with pointers in your 'equal' function (which is very un C++ like). 这允许您更自然地使用标准算法,而不是在“相等”函数中使用指针(这非常不像C ++)。

#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>

class Shape
{
    public:
        ~Shape()    {}
        bool operator==(Shape const& rhs) const
        {
            if (typeid(*this) != typeid(rhs))
            {
                return false;
            }

            return this->isEqual(rhs);
        }
    private:
        virtual bool isEqual(Shape const& rhs) const    = 0;
};

class Circle: public Shape
{
    public:
        Circle(int r)
            :radius(r)
        {}
    private:
        virtual bool isEqual(Shape const& r) const
        {
            Circle const&   rhs = dynamic_cast<Circle const&>(r);
            return radius == rhs.radius;
        }
        int radius;
};
class Rectangle: public Shape
{
    public:
        Rectangle(int h,int w)
            :height(h)
            ,width(w)
        {}
    private:
        virtual bool isEqual(Shape const& r) const
        {
            Rectangle   const&  rhs = dynamic_cast<Rectangle const&>(r);
             return (height == rhs.height) && (width == rhs.width);
        }
        int height;
        int width;
};


int main()
{

    boost::ptr_vector<Shape>    data;

    data.push_back(new Circle(5));
    data.push_back(new Circle(6));
    data.push_back(new Rectangle(7,4));

    boost::ptr_vector<Shape>::iterator f;
    f = find(data.begin(),data.end(),Circle(6));

    std::cout << "Find(" << (f - data.begin() ) << ")" << std::endl;


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM