首先我要说的是,我有一个内部有数千个向量的向量。这些内部向量中的每一个都有数千个数字。我希望尽可能保持内存管理的安全性和内存使用率。
我想问一下,如果我有类似下面的代码
int size = 10;
vector<vector<double>>* something = new vector<vector<double>>(size);
vector<double>* insideOfSomething;
for(int i = 0; i < size; i++){
insideOfSomething = &(something->at(i));
//...
//do something with insideOfSomething
//...
}
我知道将在堆中创建'某事'。我不明白的是向量的位置,'insideOfSomething'点?如果它们是在堆栈中创建的,那么这意味着我有一个向量指针,它指向堆中的向量,其中包含在堆栈中创建的向量? (我现在很困惑。)
如果我的代码与下面的代码类似;
vector<vector<double>*>* something = new vector<vector<double>*>(size);
vector<double>* insideOfSomething;
for(int i = 0; i < size; i++){
something->at(i) = new vector<double>();
insideOfSomething = something->at(i);
//...
//do something with inside insideOfSomething
//...
}
正确知道我的所有向量都存储在堆中,对吧?
根据内存管理,哪一个更有用?
答案 0 :(得分:7)
您应该避免在堆上分配向量,只是在堆栈上声明它们,因为向量将为您管理堆上的对象。在您想要避免创建副本的任何地方,您只需使用引用或const
引用(这是必要的)。
vector<vector<double> > something(size);
for(int i = 0; i < size; i++)
{
vector<double> &insideOfSomething = something.at(i);
//use insideOfSomething
}
答案 1 :(得分:4)
让我们对vector进行随机,简单的实现,因为我认为这会对你有帮助。
template <class T, class Alloc>
class vector
{
private:
T* buffer;
std::size_t vector_size;
std::size_t vector_capacity
Alloc alloc;
public:
...
};
在这种情况下,如果我们写:
vector<int> v;
v.push_back(123);
...指针buffer
,积分:vector_size
和vector_capacity
,分配器对象alloc
将全部在堆栈上创建(沿分配结构填充和对齐所需的任何额外内存。)
但是,vector本身将在堆上分配内存,buffer
指针将存储其基址。这将永远在堆上,并将包含我们想到的矢量的实际内容。
这比这更有效:
vector<int>* v = new vector<int>;
v->push_back(123);
...
delete v;
...因为这将涉及向量本身(包括其数据成员)的堆分配/释放,除了存储器向量本身为其内部内容(缓冲区)分配。它还引入了额外的间接层。
现在,如果我们有一个Somethings
向量(向量或其他任何东西):
vector<Something> v;
这些Something
实例总是在连续的堆缓冲区中分配,因为它们将驻留在向量在内部创建和销毁的动态分配的内存块中。
答案 2 :(得分:3)
在向量&lt;&gt;中存储在堆中的所有数据 而且我认为你应该简单地使用
vector< vector<double> > something;
答案 3 :(得分:1)
我希望尽可能保持内存管理的安全性和内存使用率。
然后
vector<vector<double>>* something = new vector<vector<double>>(size);
已经不好了。正如在其他答案中所说的那样,vector
已经在堆上有数据,不需要使用new
来实现这一点。事实上,对象的位置就像
S t a c k H e a p
(vector<double>) sthng[0]
(vector<vector<double>>) sthng (vector<double>) sthng[1]
...
- - - - - -
(double) sthng[0][0]
(double) sthng[0][1]
...
- - - - - -
(double) sthng[1][0]
(double) sthng[1][1]
...
(当然,堆上没有特定的块排序)
答案 4 :(得分:0)
Joe和hired777的答案解释了无论如何都会在堆上分配一个向量。我会试着给出一些有关原因的见解。
矢量是可调整大小的容器。通常,当它达到容量时它的大小增加一倍,这意味着它需要能够分配比已经分配的内存更多的内存。因此,即使你在一个函数内部并因此在堆栈中声明向量,内部它在堆上保存一个指向它的数据的指针,并且在离开函数的作用域时,它的析构函数将从堆中删除这些数据。