检查指针到向量C 内的对象
Inspecting pointers to objects inside a vector C++
我目前正在浏览一些代码,目前我有一个公路课,带有通向车道的指针(一个私人成员),该道路类包括车道课。该车道类包含指向车辆的向量,这是另一个包含简单 get 和 set 功能的类,以更新和获得车辆的位置,速度等。现在,我让车辆在单独的车道中移动,我允许它们切换车道,因为它在交通流量下。但是,我希望我的车辆能够不断找到距离距离的距离,即在前面的车辆,即在车辆矢量中查找并找到最接近的车辆。然后,我打算使用它来指示汽车是否应减速。我还想确保带领其余的汽车,因为一旦车辆离开显示屏高度,就应该删除它们。
我对此的尝试如下:
void Lane::Simulate(double time)
{ // This simulate allows check between other vehicles.
double forwardDistance = 0;
for (unsigned int iV = 0; iV < fVehicles.size(); iV++)
{
for(unsigned int jV = 0; jV < fVehicles.size(); jV++)
{
forwardDistance = fVehicles[iV]->getPosition() - fVehicles[jV]->getPosition();
}
}
if(fVehicles.size() < 15)
{
addRanVehicle(); // Adds a vehicle, with position zero but random velocities, to each lane.
}
for (unsigned int iVehicle = 0; iVehicle < fVehicles.size(); iVehicle++)
{
fVehicles[iVehicle]->Simulate(time); // Updates position based on time, velocity and acceleration.
}
}
可能有一个比使用此forwardDistance
参数更好的方法。这个想法是在每对车辆上循环,避开点iV == jV
,然后找到在Ivth车辆前面的车辆,并将两辆车之间的距离记录到setDistance()功能(这是我的功能)车辆课)。然后,我应该能够使用它来检查汽车是否太近,检查它是否可以超越,或者它是否必须制动。
目前,我不确定如何为此做出有效的循环机制。
研究在车道中执行Vehicle
s有序插入的成本。如果Vehicle
s根据道路上的位置进行排序,则检测两个Vehicle
S的距离是孩子的游戏:
例如
for (size_t n = 0; n < fVehicles.size() - 1; n++)
{
distance = fVehicles[n].getPosition() - fVehicles[n+1].getPosition();
}
这是o(n)vs o(n ^ 2)(使用 ^作为指数,而不是XOR)。这种简化的价格是需要有序插入到fVehicles
中,这应该是O(n):一个std::binary_search
来检测插入点,并且fVehicles
要求释放空间以放置Vehicle
。
维持fVehicles
的顺序在其他地方也可能是有益的。可视化列表(图形上或通过打印语句)会更加容易,当一切都以可预测的顺序和CPU时,调试在人的大脑上通常会更容易,而CPU ...他们 love 在一个不错的情况下进行,可预测的直线。有时,您会得到您没有看到的表演提升。在这里写的很棒的文章:为什么处理排序的数组比未分类的数组更快?
确定是否更好的唯一方法是尝试并测量它。
其他建议:
不要对车辆使用指针。
他们不仅难以管理,而且可以使您慢下来。如上所述,现代CPU确实擅长直线进行,并且指针可以在那条直线上扭曲。
您永远不知道在动态内存中,指针将与您所看的最后一个指针相对。但是,在Vehicle
s的连续块中,当CPU加载Vehicle
N时,它也可能抓住Vehicle
S N 1和N 2。如果因为它们太大而不能,那就没关系了,因为它已经知道它们在哪里,而CPU正在处理,而空闲的内存频道可能会向前读取并抓住您需要的数据很快。
使用指针,您每次将Vehicle
从车道移动到车道时都可以节省一些(指针通常比复制的对象便宜得多),但是在每个模拟tick中的每个循环迭代中都可能会遭受痛苦真的加起来了。C 的God-emperor Bjarne Stroustrup使用链接列表作为示例在此问题上写了一个出色的文章(注意链接列表通常比vector
指针的CC_15差,但这个想法是相同的)。
利用std::deque
。
std::vector
确实擅长于堆栈般的行为。您可以快速添加并从末端删除,但是如果从头开始添加或删除,则vector
中的所有内容都会移动。
大多数车道插入很可能处于一端,而另一端的拆卸仅仅是因为较旧的 Vehicle
s会朝着末端倾斜,因为 Vehicle
s被添加到开始中,反之亦然。如果采取建议1并排序fVehicles
,这是可以肯定的。一开始将在车道上添加新车辆,其中一些车道会将车道换入或从中间换出,并且将从末端拆除旧车辆。deque
经过优化,用于在两端插入和卸下,因此添加新车很便宜,卸下旧车便宜,并且您只为更换车道的汽车支付全价。
std::deque
上的文档
附录
尽可能利用基于范围的for
。基于范围的大部分迭代逻辑并将其隐藏在您身上。
,例如这个
for (unsigned int iV = 0; iV < fVehicles.size(); iV++)
{
for(unsigned int jV = 0; jV < fVehicles.size(); jV++)
{
forwardDistance = fVehicles[iV]->getPosition() - fVehicles[jV]->getPosition();
}
}
变成
for (auto v_outer: fVehicles)
{
for (auto v_inner: fVehicles)
{
forwardDistance = v_outer->getPosition() - v_inner->getPosition();
}
}
如果您在计数行,看起来不会好多了,但是您不能意外
iV <= fVehicles.size()
或
fVehicles[iV]->getPosition() - fVehicles[iV]->getPosition()
它消除了您造成愚蠢,致命和难以遇到的错误的可能性。
让我们分解一个:
for (auto v_outer: fVehicles)
^ ^ ^
type | |
variable name |
Container to iterate
关于
基于范围的文档在这种情况下,我还利用auto
。auto
允许编译器选择数据的类型。编译器知道fVehicles
包含Vehicle
s的指针,因此为您替换auto
。如果您稍后发现自己在重构代码,这会消除一些头痛。
auto
上的文档
不幸的是,在这罐中,它也可以捕获您。如果您遵循上面的建议,fVehicles
变为
std::dequeue<Vehicle> fVehicles;
这意味着auto
现在是Vehicle
。这使v_outer
成为副本,使您复制时间和含义,含义如果您更改v_outer
,则更改副本,而原件则不变。为了避免这种情况,倾向于
for (auto &v_outer: fVehicles)
编译器擅长确定如何最好地处理该参考或是否需要它。
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 从多个源构造一个对象,包括一个对象向量
- 如何从文件中读取两个字符串和数字数组,并将它们存储在对象向量中
- 对象 C++ 向量的 STL 容器
- 初始化C++中的对象向量
- 从自定义类获取对象向量中的 max 元素
- 如何在 c++ 中打印存档中的对象向量
- 如何将包含另一个对象向量的对象保存到文件中,并使用C++中的二进制文件从文件中读回?
- 尝试重载输出运算符时,我无法遍历对象向量
- 如何在C++中打印对象向量的内容
- 打印出对象向量中的每个元素C++
- 在 c++ 的构造函数中分配对象向量时出错
- 遍历对象向量,并找到与从文本文件中提取的对象匹配的变量
- 对象向量是否在堆或堆栈上分配C++?
- 基于不同字段的对象向量的排序功能
- 有没有一种简单的方法可以在对象向量上调用构造函数?
- 用rapidjson读取子对象向量
- 尝试使用比较运算符对对象向量进行排序
- 如何用对象向量重载 cin(>>)
- 如何将某个元素从shared_ptr擦除到对象向量?