如何删除对象指针向量中的指针和对象本身?
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 【问题描述】:我正在尝试编写一个基于文本的冒险游戏构建器。我有三个班级:Room
、Object
和我的main
班级。在我的Room
类中,我有一个Objects
指针的(私有)向量:vector<Object*> objectsInRoom
这会跟踪每个房间中存储的所有Objects
。我在Room
类中有一个名为objects()
的函数,当我在main
类中调用该向量时,它返回objectsInRooms
。
vector<Object*> Room::objects() return objectsInRoom;
在我的main
类中,在我的函数pickUpObject()
中,我创建了一个名为roomObject.
的Objects
指针向量我在Room
类中调用objects()
并存储Objects
在objectsInRoom
中(只能在Room
类中访问)在roomObject
中(可以在main
中的我的函数中访问)。我还有一个名为allObjects
的Objects
向量,它存储了我想从房间里拿起并随身携带的所有物品。它具有全球范围。
我想这样做,如果我在一个特定的房间里拿起一个物品,我把它添加到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()
返回一个 reference 到 objectsInRoom
,例如:
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
接收的是实际Object
s 的副本,而不是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;
....
否则,不要像你一样将Object
与Object*
混用,在任何地方都使用Object*
。
如果您有一组固定的游戏Object
s,我会创建一个全局vector<Object>
来保存它们,然后根据需要在任何地方传递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<unique_ptr<Object>>
,让编译器和 STL 为您处理繁重的工作.如果您发现自己不得不写类似deleteVectorContent()
的东西,请重新考虑您的设计。
【讨论】:
感谢您提供如此详细的答案。我的老师只希望我们使用原始指针。当我在pickUpObject
中引用objectsInRoom
时,我将如何删除我的“对象”指针向量?我知道你不鼓励像 deleteVectorContent
这样的函数,但如果我把它放在我的 Room
类中,那会起作用吗?以上是关于如何删除对象指针向量中的指针和对象本身?的主要内容,如果未能解决你的问题,请参考以下文章