如何删除对象指针向量中的指针和对象本身?

Posted

技术标签:

【中文标题】如何删除对象指针向量中的指针和对象本身?【英文标题】:How do you delete both a pointer in a vector of pointers of Objects and the Object itself? 【发布时间】:2018-01-25 00:05:25 【问题描述】:

我正在尝试编写一个基于文本的冒险游戏构建器。我有三个班级:RoomObject 和我的main 班级。在我的Room 类中,我有一个Objects 指针的(私有)向量:vector<Object*> objectsInRoom

这会跟踪每个房间中存储的所有Objects。我在Room 类中有一个名为objects() 的函数,当我在main 类中调用该向量时,它返回objectsInRooms

vector<Object*> Room::objects()    return objectsInRoom;  

在我的main 类中,在我的函数pickUpObject() 中,我创建了一个名为roomObject.Objects 指针向量我在Room 类中调用objects() 并存储ObjectsobjectsInRoom 中(只能在Room 类中访问)在roomObject 中(可以在main 中的我的函数中访问)。我还有一个名为allObjectsObjects 向量,它存储了我想从房间里拿起并随身携带的所有物品。它具有全球范围。

我想这样做,如果我在一个特定的房间里拿起一个物品,我把它添加到allObjects,删除roomObjects中指向那个元素的指针(以及指向那个的指针Room 类中的 objectsInRooms 中的元素)和项目本身。

我的pickUpObject 函数是:(Room* current 只是告诉我我在哪个房间,因此Objects 我有什么)

void pickUpObject(vector<Object>&allObjects, Room* current)

    vector<Object*>roomObjects;  int length; string name; char flag;
    roomObjects = current->objects();
    length = roomObjects.size(); 

    bool repeat = true; 
    while (repeat)
    
        if (length == 0)
        
            cout << "There are no objects to pick up in " << current->name() << endl;
            repeat = false; 
        
        else
        
            cout << "There is a ";
            for (int k = 0; k < roomObjects.size() - 1; k++)
            
                cout << roomObjects[k]->getName();
                if (length > 2)
                    cout << ", ";
            
            if (length > 1)
                cout << " and " << roomObjects[length - 1]->getName() << " here." << endl;
            else
                cout << roomObjects[length-1]->getName() << "." << endl;

            cout << "What object do you want to pick up?" << endl;
            cin >> name;

            //this is where the deletion happens 
            for (int i = 0; i < length; i++)
                if (name.compare(roomObjects[i]->getName()) == 0)
                                                               
                    allObjects.push_back(*roomObjects[i]);                      
                    roomObjects.erase(roomObjects.begin() + i);
                    deleteVectorContent(roomObjects, i, i + 1); 

                
            cout << "roomObject size = " << roomObjects.size() << endl; 
            cout << "--------------------" << endl; 
            cout << "allObject size = " <<  allObjects.size() << endl; 
            for (int i = 0; i < allObjects.size(); i++)
                cout << allObjects[i].getName() << endl; 


            for (int i = 0; i < roomObjects.size(); i++)
            
                cout << roomObjects[i]->getName() << endl; 
            

            cout << "Do you want to pick up another object? (Y/N): "; 
            cin >> flag; 
            if (flag == 'N')
                repeat = false; 
        
    



我查看了 *** 上的各种帖子,试图解决我的困境。在main 中,我创建了一个名为deleteVectorContent 的方法来尝试删除指针。

void deleteVectorContent(vector<Object*> objectVector, int start, int stop)

    for (int k = start; k < stop; k++)
        delete objectVector[k];
    objectVector.clear(); 

我还尝试使用“roomObjects.remove()”将项目本身从该房间中移除。然而,每当我编译时,我的编译器也会抛出一个异常。帮助将不胜感激。

附:此作业的链接是here。如果您向下滚动到“编程作业的额外学分”并转到第一个标记为“10 分”的项目,这就是我正在做的事情。非常感谢您的帮助!

【问题讨论】:

What is meant by Resource Acquisition is Initialization (RAII)?的可能重复 【参考方案1】:

Room::objects() 正在返回objectsInRoom副本,因此pickUpObject() 对该返回向量所做的任何修改都不会应用回objectsInRoom。您需要让 Room::objects() 返回一个 referenceobjectsInRoom,例如:

vector<Object*>& Room::objects()

    return objectsInRoom;


void pickUpObject(vector<Object> &allObjects, Room* current)

    vector<Object*> &roomObjects = current->objects();
    ...

否则,根本不提供对objectsInRoom直接访问权限。向Room 引入新方法以从其objectsInRoom 访问/删除给定的Object*,例如:

int Room::numObjects()

    return objectsInRoom.size();


Object* Room::getObject(int index)

    return objectsInRoom[index];


Object* Room::takeObject(int index)

    Object *obj = objectsInRoom[index];
    objectsInRoom.erase(objectsInRoom.begin()+index);
    return obj;


void pickUpObject(vector<Object> &allObjects, Room* current)

    int length = current->numObjects();
    ...
    for (int i = 0; i < length; ++i)
    
        if (name == current->getObject(i)->getName())
                                                       
            Object *obj = current->takeObject(i);
            allObjects.push_back(*obj);
            delete obj;
            break;
        
    
    ...

注意allObjects 接收的是实际Objects 的副本,而不是Object* 指针。当您复制*roomObjects[i] 然后在i 复制erase() Object* 而没有delete'ing Object 它指向时,您显示的代码正在泄漏内存。如果Object 如此容易复制,您只需摆脱所有Object* 指针并在任何地方使用Object 即可省去很多麻烦:

class Room

    vector<Object> objectsInRoom;
    ...
;

int Room::numObjects()

    return objectsInRoom.size();


Object& Room::getObject(int index)

    return objectsInRoom[index];


Object Room::takeObject(int index)

    Object obj = objectsInRoom[index];
    objectsInRoom.erase(objectsInRoom.begin()+index);
    return obj;


void pickUpObject(vector<Object> &allObjects, Room* current)

    int length = current->numObjects();
    ...
    for (int i = 0; i < length; ++i)
    
        if (name == current->getObject(i)->getName())
                                                       
            allObjects.push_back(current->takeObject(i));
            break;
        
    
    ....

否则,不要像你一样将ObjectObject* 混用,在任何地方都使用Object*

如果您有一组固定的游戏Objects,我会创建一个全局vector&lt;Object&gt; 来保存它们,然后根据需要在任何地方传递Object* 指针。那你就完全不用担心手动清理内存了:

vector<Object> allGameObjects;
// fill as needed...

void Room::addObject(Object *obj)

    objectsInRoom.push_back(obj);


Object* Room::takeObject(int index)

    Object *obj = objectsInRoom[index];
    objectsInRoom.erase(objectsInRoom.begin()+index);
    return obj;


void pickUpObject(vector<Object*> &allObjects, Room* current)

    ...
    allObjects.push_back(current->takeObject(i));
    ...

如果您绝对需要一个拥有 Object* 指针的 vector 必须在 vector 被销毁之前清理,请考虑为此使用 vector&lt;unique_ptr&lt;Object&gt;&gt;,让编译器和 STL 为您处理繁重的工作.如果您发现自己不得不写类似deleteVectorContent() 的东西,请重新考虑您的设计。

【讨论】:

感谢您提供如此详细的答案。我的老师只希望我们使用原始指针。当我在pickUpObject 中引用objectsInRoom 时,我将如何删除我的“对象”指针向量?我知道你不鼓励像 deleteVectorContent 这样的函数,但如果我把它放在我的 Room 类中,那会起作用吗?

以上是关于如何删除对象指针向量中的指针和对象本身?的主要内容,如果未能解决你的问题,请参考以下文章

当向量在内部类中时,如何删除指向对象的向量指针

如何使用类成员搜索对象指针向量?

在删除指向动态分配对象的指针向量中的元素之前,我需要做啥?

如何释放向量中的指针?

我是不是正确删除了指向对象的指针向量?

如果已删除,如何从向量中删除对象