std :: vector <std :: vector <t>&gt; vs std :: vector <t *> </t *> </std :: vector <t>

时间:2014-01-09 15:09:32

标签: c++ arrays pointers vector

鉴于内存开销对我的应用程序至关重要,我认为上面两个选项中,后者将更轻量级。我对么?我的基础是,向量的内存开销为4个指针,以跟踪begin()end()size()和分配器。所以整个模型的总大小将是

的顺序
(4*sizeof(T*) + sizeof(T)*Ni)*No + 3*sizeof(std::vector<T>*)

在这里,我假设NiNo是内部和外部向量中的元素数量。通过使用后一个表达式,我希望保存4*sizeof(T*)*No,因为在我的应用程序中,No是巨大的,而Ni <<<< No。只是为了解决问题,No的顺序为100百万及以上,Ni的顺序通常为350

提前感谢您的兴趣和想法。

注意:我理解并且非常乐意支付处理指针的价格。分配,遍历和解除分配,我可以在没有任何重大性能开销的情况下这样做。

4 个答案:

答案 0 :(得分:2)

实际上是4,你错过了分配器。见What is the overhead cost of an empty vector?

取决于您的申请。 你永远不会附加内部向量吗? 他们都有相同数量的元素吗? 内部向量中存储的数据的平均大小是否很小?

如果您对上述所有问题的回答都是肯定的,那么T*可能是一个可接受的解决方案。 如果不考虑如何在没有矢量支持的情况下处理该问题。记住内存可能更容易。

答案 1 :(得分:1)

如您所见herestd::vector的确切开销取决于实现。

另请注意,如果No非常大,则很可能在某些实现中您的数据将以块的形式存储,在这种情况下,您还需要具有块数量级的开销。

但总的来说,我同意指针实现在空间方面更便宜。

答案 2 :(得分:1)

  

我认为[vector<T*>会更好。我是对的吗?

它会更小,但不一定“更好”。这种变化会让你有必要分配和释放内部数组。你将无法知道内部数组的大小。

另请注意,大小上的一些开销将保留:只要您的内部数组是单独分配的,除了请求的块的大小之外,分配器还会保留一些额外的存储空间,以便让释放例程知道大小大块的。

如果你的内存要求太紧,可以考虑为整个数组分配一个向量,然后将各个块分成一个指针向量。这将消除单独分配内部数组的每块开销。

答案 3 :(得分:1)

如果您担心向量的开销,您还应该关注malloc() / new的开销:典型的内存分配器开销是每个内存区域至少两个指针,带来一个小vector<>的开销,最多五个指针(在Linux上为sizeof(vector<int>) == 3*sizeof(void*))。

所以,我要做的是问自己,内部数组的大小是否需要在初始化后更改。如果可以避免以后重新分配那些数组,我会分配一大块内存,然后我可以分配到不同的内部数组,只存储它们的位置:

int** pointerArray = new int*[innerArrayCount + 1];
int* store = new int[totalSizeOfInnerArrays];
for(int* nextArray = store, i = 0; i <= innerArrayCount; i++) {
    pointerArray[i] = nextArray;
    nextArray += innerArraySize[i];
}

然后可以从下一个指针和它自己的指针的差异推导出数组的大小:

for(int i = 0; i < innerArrayCount; i++) {
    int* curArray = pointerArray[i];
    size_t curSize = pointerArray[i + 1] - pointerArray[i];
    //Do whatever you like with curArray.
}

或者,您可以直接使用该结束指针迭代内部数组:

for(int i = 0; i < innerArrayCount; i++) {
    for(int* iterator = pointerArray[i]; iterator < pointerArray[i + 1]; iterator++) {
        //Do whatever you like with *iterator.
    }
}