1

我有一长串数据(n 个实体)。这个数组中的每个对象都有一些值(比如说,一个对象的m个值)。我有一个像这样的循环:

myType* A; 

// reading the array of objects   
std::vector<anotherType> targetArray;
int i, j, k = 0;
for (i = 0; i < n; i++)
     for (j = 0; j < m; j++)
     { 
         if (check((A[i].fields[j]))
         {
             // creating and adding the object to targetArray
             targetArray[k] = someGenerator(A[i].fields[j]);
             k++;
         }
     } 

在某些情况下,我有n * m有效对象,在某些 ( n * m ) /10 或更少。
问题是如何分配内存targetArray

  1. targetArray.reserve(n*m);
    // Do work
    targetArray.shrink_to_fit();

  2. 在不生成对象的情况下计算元素,然后根据需要分配尽可能多的内存并再循环一次。

  3. 在每次创建新对象的迭代中调整数组的大小。

我在我的每一种方法中都看到了一个巨大的战术错误。有另一种方法吗?

4

2 回答 2

6

您在这里所做的称为过早优化。默认情况下,std::vector它将以指数方式增加其内存占用,因为它耗尽内存来存储新对象。例如,第一个push_back将分配 2 个元素。第三个push_back将使大小加倍等。坚持push_back并让您的代码正常工作。

只有当上述方法证明自己是您设计中的瓶颈时,您才应该开始考虑内存分配优化。如果发生这种情况,我认为最好的办法是为许多有效对象提供一个很好的近似值,然后调用reserve()一个向量。类似于您的第一种方法。只需确保您的缩小以适应实现是正确的,因为向量不喜欢缩小。你必须使用swap.

在每一步都调整数组大小是不好的,std::vector除非你努力尝试,否则不会真正做到这一点。

对对象列表进行额外的循环可能会有所帮助,但也可能会造成伤害,因为您很容易浪费 CPU 周期、膨胀 CPU 缓存等。如果有疑问 - 对其进行分析。

于 2012-07-01T17:55:56.650 回答
4

典型的方法是使用 targetArray.push_back()。这会在需要时重新分配内存,并避免两次通过您的数据。它有一个重新分配内存的系统,使其非常高效,随着向量变大,重新分配的次数更少。

但是,如果您的 check() 函数非常快,您可能会通过两次检查数据来获得更好的性能,确定您需要多少内存并让您的向量一开始就具有正确的大小。如果分析确定确实有必要,我只会这样做。

于 2012-07-01T17:44:14.823 回答