添加元素后,如何停止添加到std::vector
我正在尝试进行 boids 模拟。我目前正在做的是检查 boids 是否在彼此的范围内,如果它们在,则将它们的内存地址添加到std::vector被调用的地址withinSensoryRange中。这是代码。
struct Boid
{
float sensoryRadius = 50.0f;
std::vector<Boid*> withinSensoryRange;
};
std::vector<Boid> boids;
while (true)
{
for (int i = 0; i < boids.size(); i++)
for (int j = i; j < boids.size(); j++)
{
float distance = sqrtf((boids[i].position.x - boids[j].position.x) * (boids[i].position.x - boids[j].position.x) +
(boids[i].position.y - boids[j].position.y) * (boids[i].position.y - boids[j].position.y));
if (distance > boids[i].sensoryRadius)
{
boids[i].withinSensoryRange.push_back(&boids[j]);
boids[j].withinSensoryRange.push_back(&boids[i]);
}
}
}
我的问题是,只要它们在范围内,它就会在每一帧不断地添加到向量中。有没有办法检测它是否已经在向量中,如果是就不要添加它?谢谢。
回答
您可以使用它std::find来检查容器中是否已存在项目。或者您可以使用包含唯一键的容器,例如std::unordered_set.
警告!!
存储地址时需要非常小心。如果对象移动或超出范围,则地址无效。这实际上是您的示例中可能发生的情况,因为std::vector会在调整大小时移动对象。
解决方案:
- 而是关联并存储一些唯一标识符
- 使用
std::unique_ptr(std::vector<std::unique_ptr<Boid>> boids;),这将确保对象不会移动(移动的是智能指针) - make
boidsvector 或 set const (在构造时初始化它)并确保包含对象(如果有)不会通过指针在整个访问过程中移动。 - 使用在调整大小时不会使迭代器失效的容器,例如
std::list
我试着用 std::unique_ptr 的方式来做。当我尝试推回内存地址时它不起作用
withinSensoryRange 应该是原始指针的向量:
struct Boid
{
float sensoryRadius = 50.0f;
std::vector<Boid*> withinSensoryRange;
};
std::vector<std::unique_ptr<Boid>> boids;
//...
boids[i]->withinSensoryRange.push_back(boids[j].get())