矢量指针内存分配矢量

时间:2012-02-28 18:52:31

标签: c++

首先我要说的是,我有一个内部有数千个向量的向量。这些内部向量中的每一个都有数千个数字。我希望尽可能保持内存管理的安全性和内存使用率。

我想问一下,如果我有类似下面的代码

    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 
    //...
}

正确知道我的所有向量都存储在堆中,对吧?

根据内存管理,哪一个更有用?

5 个答案:

答案 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_sizevector_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的答案解释了无论如何都会在堆上分配一个向量。我会试着给出一些有关原因的见解。

矢量是可调整大小的容器。通常,当它达到容量时它的大小增加一倍,这意味着它需要能够分配比已经分配的内存更多的内存。因此,即使你在一个函数内部并因此在堆栈中声明向量,内部它在堆上保存一个指向它的数据的指针,并且在离开函数的作用域时,它的析构函数将从堆中删除这些数据。