我是 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
。 -类(class)。
为什么多态不起作用?
std::vector<Enemy>
存储一个完整的Enemy
通过复制它在它的内存中。例如,如果 Enemy
在内存中占用 8 个字节,并且 vector 中有 5 个敌人,理论上它将占用 40 个字节的内存(可能需要更多,但这是特定于实现的)
| Idx0 | Idx1 | Idx2 | Idx3 | Idx4 |
[Enemy1][Enemy2][Enemy3][Enemy4][Enemy5]
8b 8b 8b 8b 8b
如果您尝试存储派生的 ExtraToughEnemy
在位置 3 添加属性的对象需要比方说 4 个额外字节,它不会工作,因为 vector 中的每个条目都必须具有相同的大小。
| 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
在堆上创建对象。
关于c++ - 如何删除尚未分配给对象的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21966745/