如何删除尚未分配给对象的指针
How to delete pointer which has not been assigned to an object
我是C++的新手,目前正在开发一款游戏。在游戏中,随着时间的推移,我会随机生成敌人,我使用std::vector来实现这一点。我想我可以用之类的东西
enemies.push_back(new Enemy(random_x, randomY));
在循环中,但现在我觉得这可能会导致内存泄漏,因为我没有删除指针。所以我想知道我应该怎么做才能防止内存泄漏;我应该找到一种方法来删除我创建的所有敌人,还是应该做一些完全不同的事情?
有多种方法可以解决这个问题。
您可以使用原始指针,如在std::vector<Enemy*>
中,然后您需要在删除它们的同时删除它们:
delete *pos; // pos is an iterator pointing to the element to be deleted
enemies.erase(pos);
然而,这不是用C++处理事情的方法。
如果您想在没有访问列表的情况下传递"敌人",可以使用shared_ptr
,如std::vector<std::shared_ptr<Enemy>>
中所示。然后你只需要擦除,一旦不再存在指向敌人的shared_ptr
,内存就会自动为你释放。
enemies.erase(pos); // Nothing more needed, if someone still has a shared_ptr-copy
// of the enemy it will stay in memory until that reference is gone
如果你总是使用列表来访问敌人,你甚至可以使用std::unique_ptr
。但在这种情况下,最好使用最简单的形式:std::vector<Enemy>
。这样,您就不必调用new
。但这也阻止了您使用多态性,并且根据您的Enemy
-类,副本可能非常昂贵。
为什么多态性不起作用
std::vector<Enemy>
通过复制将完整的Enemy
存储在内存中。例如,如果Enemy
占用内存中的8个字节,而你在向量中有5个敌人,理论上它将占用40个字节的内存(可能需要更多,但这是特定于实现的)
| Idx0 | Idx1 | Idx2 | Idx3 | Idx4 |
[Enemy1][Enemy2][Enemy3][Enemy4][Enemy5]
8b 8b 8b 8b 8b
如果您试图在位置3存储一个添加了属性的派生ExtraToughEnemy
对象,比如说需要额外的4个字节,那么它将不起作用,因为向量中的每个条目都必须具有相同的大小。
| Idx0 | Idx1 | Idx2 | Idx3 | Idx4 |
[Enemy1][Enemy2][ExtraToughEnemy3][Enemy4][Enemy5]
8b 8b 12b 8b 8b
如果使用指针,可以避免这个问题,因为每个指针对象都有相同的大小,但可以指向不同的派生对象。
| Idx0 | Idx1 | Idx2 | Idx3 | Idx4 |
[Enemy1*][Enemy2*][Enemy3*][Enemy4*][Enemy5*]
4b 4b 4b 4b 4b
基类指针可以指向任何基类或派生对象。不过,您必须使用强制转换来访问Enemy3*
的额外属性。
关于共享指针和唯一指针的注意事项:
如果使用它们,您可以考虑(取决于编译器),甚至完全跳过使用new
,使用std::make_shared
或std::make_unique
在堆上创建对象。
如果您在没有首先释放后备存储的情况下失去了对对象的访问权限,那么只有内存泄漏。这里的情况并非如此,因为您只需遍历enemies
集合就可以调用find all these敌人。
大概在某个时候,你会从列表中删除敌人(例如,当你在游戏中杀死他们时)。在这一点上,你应该删除它们,内存将被回收。
- 使用操作重载对象重新分配对象
- 静态分配对象的值初始化
- C++ 将抽象类型的动态分配对象传递给函数并存储在向量中
- 堆分配对象中的堆栈对象在 c++ 中在哪里分配?
- 在 c++ 的构造函数中分配对象向量时出错
- 动态分配对象中的字段-动态分配更好还是静态分配更好?C++
- 操作后通过运算符分配对象
- 如何捕获源自静态分配对象的构造函数的异常?
- 在C++中,当重新分配对象时,为什么构造函数在析构函数之前触发?
- 如何使用每个对象的单个构造函数参数动态分配C++对象数组?
- 将动态分配对象传递到 boost::any 构造函数中
- 混合指向已分配对象和作用域对象的指针
- C 删除指向动态分配对象的指针
- 有关动态分配对象的问题
- 类的堆分配对象是否在其作用域之后但在 C++ 中调用其析构函数之前处于活动状态
- C++ 中的黑白堆分配对象和堆栈分配对象的性能差异
- 是隐式创建的默认构造函数,负责分配对象内存
- 如何删除用于动态分配对象的智能指针
- 分配对象数组时如何初始化每个对象
- 用于堆栈分配对象的C++虚拟析构函数内联