将一个向量的内容移动到另一个向量
Moving the contents of one vector to another
所以我有一个向量:
vector<Enemy*> enemies;
这个矢量包含敌人,它们是在游戏中动态创建的。
if(rand() % 1000 > 998)
{
Enemy * enemy = new Enemy(num_of_enemies);
enemies.push_back(enemy);
}
这个存在的问题是,即使敌人已经被删除,向量也会不断增长,这会减慢我的游戏速度。
本质上,我想把vector的内容移动到一个新的vector中,但只移动包含敌人的元素。
我读到有一个叫做std::move
的东西,但我不确定如何正确地执行它,或者它是否会成功地移动包含敌人的元素,而不仅仅是整个向量。
任何帮助与代码实现结构将非常感激。
这是如何处理刷出和消灭敌人的完整工作流程。注意,这里根本没有指针。
-
生成敌人:
if (if random_float_between_0_and_1() < 0.002) enemies.push_back(Enemy{arguments});
-
火的敌人;根据你下面的评论,应该看起来像这样:
auto last_iter = std::remove_if(enemies.begin(), enemies.end(), is_dead); enemies.erase(last_iter, enemies.end());
这里,
is_dead
是一个函数,它接受Enemy const&
并确定它是否与玩家或屏幕边界碰撞:bool is_dead(Enemy const& enemy) { return outside_screen_area(enemy) or near_player(enemy); }
函数
outside_screen_area
和near_player
应该很容易实现。要理解上面的代码是如何工作的,请参阅
std::remove
和std::vector::erase
的文档
另一件事:根据c++ 11附带的标准库随机库实现random_float_between_0_and_1
函数。不要在整数随机数上使用std::rand
或取模运算,它们的效果很差(即它们不是真正均匀分布的,并且会给出倾斜的结果)。
这个存在的问题是,即使敌人已经被删除,向量也会不断增长…
实际上我想把向量的内容移动到一个新的向量…
在我看来,一种更简单的方法是从原始向量中删除指向已删除对象的指针,而不是创建一个副本。
指向不再存在的已删除对象的指针与指向已存在对象的指针没有区别。因此,必须跟踪必须从vector中删除的元素。最简单的解决方案是在元素被删除后立即删除它。使用智能指针,这变得容易得多,因为删除指针也会自动删除对象。
std::move
不会帮你解决这个问题。
您可能想要考虑根本不使用手动动态分配。您可以将Enemy
对象存储在vector中。
当要删除敌人时,我调用类析构函数,然后删除
delete
表达式调用析构函数。你自己调用它也会有未定义的行为
首先,如果您想要删除随机位置的单个元素,我建议您不应该使用像std::vector这样的数据结构。该操作的复杂度与被删除元素后的元素个数线性。
据我所知,你有许多敌人在2D屏幕上与一个(或多个)玩家肩并肩地移动。如果敌人被玩家击中或离开屏幕,它将被删除。你只需循环遍历敌人列表,看看这些条件是否满足。
在这种情况下,我建议你使用std::map来管理你创建的敌人对象。
假设你的Enemy类有一个检查删除条件的函数,例如:
bool Enemy::willbeDeleted() /* if true then will be deleted */
下面是一个使用std::map管理敌人对象的类:EnemyManager.hpp
#include <map>
class EnemyManager {
public:
/*
* Get the Enemy Manager
*/
static EnemyManager& Instance();
/*!
* Delete the instance of EnemyManager
*/
static void deleteInstance();
public:
/* Create an enemy object */
void createEnemy();
/* Check all enemy objects and delete any fulfulling condition */
void checkEnemy();
virtual ~EnemyManager();
private:
/* Make sure we can not call EnemyManager constructor directly */
EnemyManager();
EnemyManager(const EnemyManager& objManager);
/* Instance of EnemyManager */
static EnemyManager* enemyManager;
private:
/* List of current enemy objects */
std::map<int, A*> enemyList_;
/* Identity of already-create object, it increases on creating a new object */
int enemyIndex_;
};
EnemyManager.cpp
#include "EnemyManager.hpp"
#include <vector>
EnemyManager* EnemyManager::enemyManager = 0;
EnemyManager& EnemyManager::Instance()
{
if (0 == enemyManager)
{
enemyManager = new EnemyManager();
}
return *enemyManager;
}
void EnemyManager::deleteInstance()
{
if (0 != enemyManager) delete enemyManager;
}
EnemyManager::EnemyManager() : enemyList_(), enemyIndex_(0)
{}
EnemyManager::~EnemyManager() {
/* Nothing todo */
}
void EnemyManager::createEnemy()
{
enemyList_[enemyIndex_] = new Enemy();
++enemyIndex_;
}
void EnemyManager::checkEnemy()
{
std::map<int, A*>::const_iterator itb = enemyList_.begin(),
ite = enemyList_.end(), it;
// Vector containing id of enemy object to delete
std::vector<int> enemyToDelete;
for (it = itb; it != ite; ++it)
if ((it->second)->willbeDeleted())
enemyToDelete.push_back(it->first);
// Delete enemies and remove them from map
for (std::size_t idx = 0; idx < enemyToDelete.size(); ++idx)
{
delete enemyList_[enemyToDelete[idx]];
enemyList_.erase(enemyToDelete[idx]);
}
}
你可以这样使用这个类:在main.cpp
EnemyManager& enemyManager = EnemyManager::Instance();
if(rand() % 1000 > 998)
{
/* Create new enemy */
enemyManager.createEnemy();
}
/* Check all enemies */
enemyManager.checkEnemy();
有两个重要的函数:createEnemy控制创建新敌人对象的方式,checkEnemy验证对象并在需要时删除它们,并且enemyList_的大小永远不会增加:)
我相信用这种方法,删除敌人不会再减慢你的程序。
这种方法的缺点之一是创建对象的数量可能会受到2^(8*sizeof(enemyIndex_))
- 如何在不复制的情况下将一个向量移动到另一个向量中
- 如何将所有指针从一个向量移动到另一个向量?
- 如何在C++中有效地将数组移动到向量
- 在将其尺寸较大的向量移动到容量较小的向量之前,是否可以通过使用Reserve()来提高代码性能
- C 可以使用MOVE SEMATICS将数据从一个向量移动到另一个向量
- 在deque实现中将1/2一个向量移动到另一个向量
- 使用擦除-删除范例将元素从一个向量移动到另一个向量
- 在C++中将对象从一个向量移动到另一个向量(LEMON 库)
- 从向量移动初始化priority_queue
- 如何将唯一指针从一个向量移动到另一个唯一指针向量
- 从字符串和向量移动以不拥有任何堆内存
- STL 向量:移动向量的所有元素
- 通过向量移动类对象
- C++ 将元素从一个向量移动到另一个向量
- 在c++中将元素从一个向量移动到另一个向量
- 从一个带有一个分配器的向量移动到另一个带有分配器的向量
- 将一个向量移动到另一个,地址没有更新
- std::数据结构中的向量移动语义
- 将一个对象向量移动到另一个向量
- 将unique_ptrs从一个向量移动到另一个向量