这个问题来源于主题:
我正在使用vector<vector<vector<double> > >
类型的数据结构。在添加项目(double
s)之前,无法知道每个向量的大小(外部向量除外)。我可以得到每个“维度”中项目数量的近似大小(上限)。
使用共享指针的解决方案可能是可行的方法,但我想尝试一种解决方案,其中vector<vector<vector<double> > >
只有.reserve()
足够的空间(或以其他方式分配足够的空间)存储器)。
请A.reserve(500)
(假设500是大小,或者大小的上限)足以容纳大尺寸的“2D”矢量,比如[1000] [10000]?
我的问题的原因主要是因为在A
时我无法合理估算.reserve(500)
内部的大小。
我的问题的一个例子:
vector<vector<vector<int> > > A;
A.reserve(500+1);
vector<vector<int> > temp2;
vector<int> temp1 (666,666);
for(int i=0;i<500;i++)
{
A.push_back(temp2);
for(int j=0; j< 10000;j++)
{
A.back().push_back(temp1);
}
}
这是否确保没有为A?
重新分配如果在创建时添加了temp2.reserve(100000)
和temp1.reserve(1000)
,这将确保根本不会发生重新分配?
在上文中,请忽略由于保守的.reserve()
电话而浪费内存的事实。
提前谢谢大家!
答案 0 :(得分:1)
如何预先在A中预留500个条目足够[1000] [1000]?
您需要保留&gt; 1000为A(这是你的实际上限值),然后每当你向A添加一个条目时,在中保留另外1000个左右(再次,上限但第二个 value)。
即
A.reserve(UPPERBOUND);
for(int i = 0; i < 10000000; ++i)
A[i].reserve(UPPERBOUND);
BTW,reserve保留元素的数量,而不是字节数。
答案 1 :(得分:1)
您的示例将导致大量复制和分配。
vector<vector<vector<double>>> A;
A.reserve(500+1);
vector<vector<double>> temp2;
vector<double> temp1 (666,666);
for(int i=0;i<500;i++)
{
A.push_back(temp2);
for(int j=0; j< 10000;j++)
{
A.back().push_back(temp1);
}
}
问:这是否可以确保不对A进行重新分配? 答:是的。
问:如果temp2.reserve(100000)和temp1.reserve(1000)在创建时添加,这将确保根本不会发生任何重新分配?
答:这里temp1已经在创建时知道它自己的长度并且不会被修改,所以添加temp1.reserve(1000)只会强制进行不需要的重新分配。
我不知道矢量类在他们的副本ctor中复制了什么,使用A.back()。reserve(10000)应该适用于这个例子。
更新:刚刚使用g ++测试,不会复制temp2的容量。所以temp2.reserve(10000)将不起作用。
请在发布代码时使用源格式化,使其更具可读性: - )。
答案 2 :(得分:1)
reserve
功能可以为您vector A
正常使用,但不会像您期望的那样temp1
和temp2
。
temp1
向量初始化为给定大小,因此将使用正确的capacity
进行设置,只要您计划,就不需要使用reserve
不要增加它的大小。
关于temp2
,capacity
属性不会在副本中转移。考虑每当您使用push_back
功能时,您都会向vector
添加副本,代码如下
vector<vector<double>> temp2;
temp2.reserve(1000);
A.push_back(temp2); //A.back().capacity() == 0
您只是增加了临时释放的临时分配内存,而不是按预期增加vector
元素容量。如果您真的想使用vector
vector
作为解决方案,则必须执行以下操作
vector<vector<double>> temp2;
A.push_back(temp2);
A.back().reserve(1000); //A.back().capacity() == 1000
答案 3 :(得分:1)
有一天我遇到了同样的问题。一个干净的方法(我认为)是编写自己的Allocator
并将其用于内部向量(std::vector<>
的最后一个模板参数)。我们的想法是编写一个实际上不分配内存的分配器,只是在外部向量的内存中返回正确的地址。如果您知道每个先前向量的大小,就可以轻松地知道这个地址。
答案 4 :(得分:1)
为了避免复制和重新分配数据结构,例如vector<vector<vector<double> > >
,我建议如下:
vector<vector<vector<double> > > myVector(FIXED_SIZE);
为了“赋值”它,在你真正知道它们的所需维度之前不要定义你的内部向量,然后使用swap()而不是赋值:
vector<vector<double> > innerVector( KNOWN_DIMENSION );
myVector[i].swap( innerVector );
请注意push_back()
将执行复制操作并可能导致重新分配,而swap()
则不会(假设两个向量都使用相同的分配器类型)。
答案 5 :(得分:0)
在我看来,你需要一个真正的矩阵类而不是嵌套向量。看看boost,它有一些强大的稀疏矩阵类。
答案 6 :(得分:0)
好的,现在我自己做了一些小规模的测试。我使用从http://www.tek-tips.com/faqs.cfm?fid=5575获得的“2DArray”来表示分配内存静态的结构。对于动态分配,我几乎按照原始帖子中的说明使用了向量。
我测试了以下代码(hr_time是在网络上发现的一个时间例程,由于反垃圾邮件,我很遗憾无法发布,但是归功于David Bolton提供它)
#include <vector>
#include "hr_time.h"
#include "2dArray.h"
#include <iostream>
using namespace std;
int main()
{
vector<int> temp;
vector<vector<int> > temp2;
CStopWatch mytimer;
mytimer.startTimer();
for(int i=0; i<1000; i++)
{
temp2.push_back(temp);
for(int j=0; j< 2000; j++)
{
temp2.back().push_back(j);
}
}
mytimer.stopTimer();
cout << "With vectors without reserved: " << mytimer.getElapsedTime() << endl;
vector<int> temp3;
vector<vector<int> > temp4;
temp3.reserve(1001);
mytimer.startTimer();
for(int i=0; i<1000; i++)
{
temp4.push_back(temp3);
for(int j=0; j< 2000; j++)
{
temp4.back().push_back(j);
}
}
mytimer.stopTimer();
cout << "With vectors with reserved: " << mytimer.getElapsedTime() << endl;
int** MyArray = Allocate2DArray<int>(1000,2000);
mytimer.startTimer();
for(int i=0; i<1000; i++)
{
for(int j=0; j< 2000; j++)
{
MyArray[i][j]=j;
}
}
mytimer.stopTimer();
cout << "With 2DArray: " << mytimer.getElapsedTime() << endl;
//Test
for(int i=0; i<1000; i++)
{
for(int j=0; j< 200; j++)
{
//cout << "My Array stores :" << MyArray[i][j] << endl;
}
}
return 0;
}
事实证明,这些尺寸大约有10倍。因此,我应该重新考虑动态分配是否适合我的应用,因为速度至关重要!
答案 7 :(得分:0)
为什么不在构造函数中对内部容器和reserve()进行子类化?
答案 8 :(得分:0)
如果Matrix确实变得非常庞大且备用,我也会尝试使用稀疏矩阵库。否则,在搞乱分配器之前,我会尝试用deque替换vector。 deque不会重新分配增长,并提供几乎与矢量一样快的随机访问。
答案 9 :(得分:0)
这或多或少回答here。所以你的代码看起来像这样:
vector<vector<vector<double> > > foo(maxdim1,
vector<vector<double> >(maxdim2,
vector<double>(maxdim3)));