向量保留c++

yv5phkfx  于 2022-12-01  发布在  其他
关注(0)|答案(4)|浏览(193)

我有一个非常大的多维向量,它的大小一直在变化。当我只知道一个很好的近似大小时,使用vector.reserve()函数有什么意义吗?
所以基本上我有一个向量
A[256*256][x][y]
y值每次可以不同,这意味着对于[256*256][y]元素中的每一个,向量y可以具有不同的大小,但是仍然小于256;
所以为了澄清我的问题,我有:

vector<vector<vector<int>>> A;
for(int i =0;i<256*256;i++){
  A.push_back(vector<vector<int>>());
  A[i].push_back(vector<int>());
  A[i][0].push_back(SOME_VALUE);
}

将元素添加到向量...

A.clear();

在这之后,我又从头开始做同样的事情。
我应该在什么时候以及如何为向量保留空间。如果我正确理解了这一点,我会节省很多时间,如果我会使用保留,因为我改变了大小的所有时间?
在某些情况下,保留向量的最大大小([256*256][50][256])的负/正边是什么?
顺便说一句。我知道不同的矩阵模板和增强,但已决定去与向量对这一个...

**EDIT:**我还想知道如何在多维数组中使用reserve函数。如果我只在二维中保留向量,那么如果我在第三维中超过了它的容量,它会复制整个向量吗?

epggiuax

epggiuax1#

为了有助于讨论,您可以考虑以下typedef:

typedef std::vector<int> int_t;   // internal vector
typedef std::vector<int_t> mid_t; // intermediate
typedef std::vector<mid_t> ext_t; // external

增加int_t的代价只会影响这个特定向量的内容,而不会影响任何其他元素。增加mid_t的代价需要复制该向量中所有存储的元素,也就是说,它将需要所有的int_t向量,这是相当昂贵的。增加ext_t的代价是巨大的:它将需要复制 * 所有 * 已经存储在容器中的元素。
现在,为了提高性能,更重要的是获得正确的ext_t大小(在您的问题中似乎是固定的256*256),然后获得正确的中间mid_t大小,这样代价高昂的重新分配就很少了。
您所讨论的内存量非常大,因此您可能需要考虑一些不太标准的方法来解决问题。首先想到的是添加额外的间接层。如果不保存实际的向量,而是保存指向向量的智能指针,则可以减少增加mid_text_t向量的成本(如果ext_t的大小是固定的,就使用一个向量mid_t).现在,这意味着使用您的数据结构的代码将更加复杂,(或者最好添加一个负责间接寻址的 Package 器)。每个int_t向量将在内存中分配一次,并且永远不会在mid_text_t重新分配中移动。重新分配mid_t的成本与分配的int_t向量的数量成比例,而不是与插入的整数的实际数量成比例。

using std::tr1::shared_ptr; // or boost::shared_ptr
typedef std::vector<int> int_t;
typedef std::vector< shared_ptr<int_t> > mid_t;
typedef std::vector< shared_ptr<mid_t> > ext_t;

另一件需要注意的事情是std::vector::clear()不会释放向量中分配的内部空间,只会破坏包含的对象并将大小设置为0。也就是说,调用clear()永远不会释放内存。实际释放向量中分配的内存的模式是:

typedef std::vector<...> myvector_type;
myvector_type myvector;
...
myvector.swap( myvector_type() ); // swap with a default constructed vector
9rygscc1

9rygscc12#

每当您将向量推入另一个向量时,请在pushed vectors建构函式中设定大小:

A.push_back(vector<vector<int> >( somesize ));
yzuktlbb

yzuktlbb3#

您有一个正在工作的实现,但担心性能问题。如果您的分析显示它是一个瓶颈,您可以考虑使用一个裸C样式的整数数组,而不是向量的向量的向量。
有关示例,请参见how-do-i-work-with-dynamic-multi-dimensional-arrays-in-c
每次都可以重复使用相同的分配,根据需要进行realloc操作,并最终将其保持在使用率的高潮标记。
如果向量确实是瓶颈,除了避免每次循环迭代对向量进行大小调整操作之外,性能可能会由您对数组的访问模式所支配。请尝试按顺序访问最高阶。

kq4fsx7k

kq4fsx7k4#

如果你在构造时知道向量的大小,那么就把它传递给c 'tor,然后用operator[]而不是push_back赋值。如果你不确定最终的大小,那么就猜测一下(可能会多加一点),然后用reserve让向量预先预留足够的内存。
在某些情况下,保留向量的最大大小(可能为[256256][50][256])的负/正边是什么?
反面:潜在的内存浪费。积极的一面:更少的CPU时间,更少的堆碎片。这是一个内存/CPU的权衡,最佳选择取决于您的应用程序。如果您没有内存限制(在大多数消费者计算机上有足够的RAM),请考虑提前预留。
要决定保留多少内存,请查看平均内存消耗,而不是峰值(保留256
25650256并不是一个好主意,除非经常需要这样的尺寸)

相关问题