C++ 向量迭代器不可解引用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/301959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:26:42  来源:igfitidea点击:

Vector iterator not dereferencable

c++stl

提问by Poorna

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. At the same time I have not overloaded == operator in any class

我有一个名为 Shape 的抽象基类,从它派生 Circle 和 Rectangle,但是当我在 VS 2005 中执行以下代码时,我收到错误 Debug assertion failed。同时我没有在任何类中重载 == 运算符

Expression:Vector iterator not dereferencable, what is the reason for this.

Expression:Vector iterator not dereferencable,这是什么原因。

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

回答by David Pierre

Simple :

简单的 :

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

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_vectoris an easy way to achieve this.

正如其他答案中所指出的,boost::ptr_vector是实现这一目标的简单方法。

回答by xtofl

Like @David Pierre suggests: find is value-based: it looks in the range of iterators for a pointer (e.g. 0x0F234420) that equals the pointer to the new Circle(point(1,2),3)you just created. Since that's a new object, it won't be there.

就像@David Pierre 建议的那样: find 是基于值的:它在迭代器的范围内查找等于new Circle(point(1,2),3)您刚刚创建的指针的指针(例如 0x0F234420)。因为那是一个新对象,它不会在那里。

You can get around this by using find_ifwith an operator that compares the objects referenced to by the pointer.

您可以通过使用find_if比较指针引用的对象的运算符来解决此问题。

However, the Criterium should be able to differentiate between shape types.

然而,标准应该能够区分形状类型。

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

回答by Martin York

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;


}