分段在向量中删除指针时出错

时间:2014-06-08 09:25:24

标签: c++ pointers vector

我试图在用户想要删除对象时删除向量中的对象指针。我试图:

  1. 删除指针
  2. 从矢量
  3. 中删除指针

    我在DataBase类中有一个字符串到向量的映射。并且向量包含指向对象的指针。像这样:

    “database.h”中objectMapobjectector的定义

    private:
        typedef std::vector<Object *> objectVector;
        typedef std::map<std::string, objectVector> objectMap;
        objectMap objects;
    

    在“database.cpp”中实施deleteId

    bool DataBase::deleteId(int id)
    {
        // vectors
        for(objectMap::iterator vec = objects.begin(); vec != objects.end(); ++vec)
        {
            objectVector v = vec->second;
            // objects
            for(objectVector::iterator obj = v.begin(); obj != v.end(); ++obj)
            {
                if((*obj)->getId() == id)
                {
                    delete *obj;  // pointer
                    *obj = 0;
                    v.erase(obj); // erase from vector
                    modified = true;
                    return true;
                }
            }
        }
        return false;
    }
    

    我目前正在尝试调试程序,我打印出整个对象地图,看看删除是否有效。问题是删除后对象指针仍然存在,即使函数确认删除(即返回true)。有人可以解释一下发生了什么吗?

2 个答案:

答案 0 :(得分:2)

objectVector v = vec->second;

按值复制矢量,因此您指的是副本,而不是真正的矢量。

建议将该行改为

objectVector& v = vec->second; // Reference to the "real" vector

使对象迭代器失效没有问题,因为一旦遇到删除元素,你就会退出该函数。

答案 1 :(得分:1)

您的代码错误至少是因为您没有删除原始向量中的元素。使用对向量的引用

for(objectMap::iterator vec = objects.begin(); vec != objects.end(); ++vec)
{
    objectVector &v = vec->second;

另外考虑一种方法,如果在向量中删除一个元素之后,向量变为空,那么也许你还应该删除映射中的相应元素。

例如)没有测试)

bool DataBase::deleteId(int id)
{
    bool modified = false;

    for ( auto it1 = objects.begin(); !modified && it1 != objects.end(); ++it1 )
    {
        auto it2 = std::find_if( it1->second.begin(), it1->second.end(),
                                 [&]( Object *o ) { return ( o->getId() == id ); } );
        modified = it2 != it1->second.end();

        if ( modified )
        {
            delete *it2;
            it1->second.erase( it2 );
            if ( it1->second.empty() ) it1 = objects.erase( it1 );
        }
    }

    return modified;
}