在这种情况下,问题场景是一款游戏,因此所有资源都在开始时分配,然后在某个级别上进行迭代。存储在向量中的对象是复杂类的实例,当然,在加载时将它们复制到向量中实际上是耗时的,但并不重要。但如果我的主要关注点是在运行时迭代类对象的速度,那么我是否应该将类对象本身存储在向量中,而不仅仅是指向类对象的指针,正如传统建议的那样?在这个例子中,我不担心内存管理,只关注迭代速度。
std::vector<A*>
这种架构比其他架构稍微慢了一些。std::vector<A*>
由于 std::vector
实现而保证是连续的,而且因为我们使用了放置 new 惯用语,A
对象本身也将在堆上连续。我使用了与此 答案 中概述的相同方法;有关放置 new 的更多信息可以在 这里 找到。在这里,我们直接使用std::vector<A>
。 std::vector
的实现保证了我们的A
对象在内存中是连续的。请注意,对象的std::vector
涉及到A
的移动和复制构造函数的考虑。为避免不必要的移动和/或重建,最好提前std::vector.reserve()
最大可能需要的大小,然后尽可能使用std::vector.emplace_back()
(而不是push_back()
)。循环遍历此结构最快,因为我们能够消除一级指针间接。
这种方法比方案1快6.4%。
与另一个问题相关的answer也显示出普通对象(作为类成员)比相应的指针(作为类成员)更快。
#include <iostream>
#include <string>
#include <vector>
#include "CHRTimer.h"
struct Items
{
std::string name;
int id;
float value;
float quantity;
};
void main()
{
std::vector<Items> vecItems1;
for(int i = 0; i < 10000; i++)
{
Items newItem;
newItem.name = "Testing";
newItem.id = i + 1;
newItem.value = 10.00;
newItem.quantity = 1.00;
vecItems1.push_back(newItem);
}
CHRTimer g_timer;
g_timer.Reset();
g_timer.Start();
for(int i = 0; i < 10000; i++)
{
Items currentItem = vecItems1[i];
}
g_timer.Stop();
float elapsedTime1 = g_timer.GetElapsedSeconds();
std::cout << "Time Taken to load Info from Vector of 10000 Objects -> " << elapsedTime1 << std::endl;
std::vector<Items*> vecItems;
for(int i = 0; i < 100000; i++)
{
Items *newItem = new Items();
newItem->name = "Testing";
newItem->id = i + 1;
newItem->value = 10.00;
newItem->quantity = 1.00;
vecItems.push_back(newItem);
}
g_timer.Reset();
g_timer.Start();
for(int i = 0; i < 100000; i++)
{
Items *currentItem = vecItems[i];
}
g_timer.Stop();
float elapsedTime = g_timer.GetElapsedSeconds();
std::cout << "\nTime Taken to load Info from Vector of 100000 pointers of Objects -> " << elapsedTime;
}