我有一个非常大的多维向量,它的大小一直在变化。 当我只知道大小的近似值时,有没有必要使用vector.reserve()函数。
所以基本上我有一个载体
A[256*256][x][y]
其中x在程序中的每次迭代中从0变为50,然后再次返回0。 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]
。
顺便说一句。我知道不同的Matrix模板和Boost,但已经决定在这个上使用向量...
修改 我也想知道如何在多维数组中使用保留函数。 如果我只保留二维向量,那么如果我超过第三维的容量,它会复制整个东西吗?
答案 0 :(得分:4)
为了帮助讨论,您可以考虑以下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_t
和ext_t
向量增长的成本(如果ext_t
大小是固定的,只需使用向量mid_t
)。现在,这意味着使用您的数据结构的代码将更复杂(或者更好地添加一个处理间接的包装器)。每个int_t
向量将在内存中分配一次,并且永远不会在mid_t
或ext_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
答案 1 :(得分:2)
每当您将矢量推入另一个矢量时,请在推送的矢量构造函数中设置大小:
A.push_back(vector<vector<int>>( somesize ));
答案 2 :(得分:0)
您有一个有效的实施方案但是对性能感到担忧。如果您的分析显示它是一个瓶颈,您可以考虑使用裸C样式的整数数组而不是向量向量的向量。
请参阅how-do-i-work-with-dynamic-multi-dimensional-arrays-in-c以获取示例
每次都可以重复使用相同的分配,realloc
根据需要,最终将其保持在使用的高潮位置。
如果向量确实是瓶颈,那么除了避免对每个循环迭代的向量进行大小调整操作之外的性能可能会被您的访问模式主导到数组中。尝试按顺序访问最高订单。
答案 3 :(得分:0)
如果您知道施工时矢量的大小,请将大小传递给c'tor并使用operator[]
代替push_back
进行分配。如果你不完全确定最终的大小,那就做一个猜测(也许再添加一点)并使用reserve
让向量预留足够的内存。
保留我的矢量可以具有的最大尺寸的负面/正面是什么?在某些情况下会是[256 * 256] [50] [256]。
否定方面:潜在的内存浪费。积极的一面:更少的CPU时间,更少的堆碎片。这是内存/ CPU的权衡,最佳选择取决于您的应用程序。如果你没有内存限制(在大多数消费者机器上有足够的内存),可以考虑预先保留。
要确定要保留多少内存,请查看平均内存消耗,而不是峰值(保留256 * 256 * 50 * 256不是一个好主意,除非定期需要这样的维度)