2012-02-28 269 views
2

首先我想說的是,我有一個矢量裏面有一千個矢量。這些內部向量中的每一個都有數千個數字。我想盡可能保持內存管理安全和內存使用最少。矢量指針內存分配矢量

我想問一下,如果我有一個代碼類同下面

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

right知道我的所有向量都存儲在堆中,對不對?

根據內存管理哪一個更有用?

回答

4

讓我們隨意,簡單的實現載體,因爲我覺得這會幫助你。

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,都將在創建堆棧(以及分配結構填充和對齊所需的額外內存)。

但是,矢量本身會在堆中分配內存,這個buffer指針將存儲其基地址。這將始終在堆上,並將包含我們認爲它們的矢量的實際內容。

這仍然比這更有效:

vector<int>* v = new vector<int>; 
v->push_back(123); 
... 
delete v; 

...因爲這將涉及用於在除了存儲器載體本身分配用於所述載體本身(包括它的數據成員)堆分配/解除分配其內部內容(緩衝區)。它還引入了額外的間接性。

現在,如果我們有Somethings(矢量或任何其他的載體)的載體:

vector<Something> v; 

那些Something實例總是將是一個連續的堆緩衝區內分配的,因爲它們將駐留在動態分配內存塊,矢量在內部創建和銷燬。

+0

tehre的副本很好的解釋。非常感謝你.. – emreakyilmaz 2012-02-28 19:56:11

3

在矢量<>存儲在堆棧 所有的數據,我想你應該簡單地使用

vector< vector<double> > something; 
+0

向量的實際聚合內容,是的。但是矢量對象通常包含一些額外的指針或整數,並且隨着代碼指出,這些矢量對象本身可以存在於堆棧中。 – stinky472 2012-02-28 19:29:29

7

你應該避免在堆中分配的載體和剛剛宣佈他們在堆棧上,因爲載體將管理它的對象在你的堆上。任何你想避免創建副本的地方都可以使用參考或const參考(這是必要的)。

vector<vector<double> > something(size); 

for(int i = 0; i < size; i++) 
{ 
    vector<double> &insideOfSomething = something.at(i); 

    //use insideOfSomething 
} 
+1

一個有趣的[相關閱讀關於複製elision](http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/)。 – 2012-02-28 19:06:37

+0

複製elision似乎沒有在這裏相關,因爲在這個樣本 – 2012-02-28 20:02:39

0

喬和hired777的答案解釋說,無論如何,矢量將分配在堆上。我會盡力就這個原因提供一些見解。

矢量是可調整大小的容器。一般來說,當它達到容量時它的容量就會增加一倍,這意味着它需要能夠分配比已經分配的更多的內存。因此,即使當你在一個函數中聲明向量,並因此在棧中聲明向量時,它在內部持有一個指向它在堆上的數據的指針,並且在離開函數的作用域時,析構函數會從堆中刪除這些數據。

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] 
               ... 

(當然,對堆塊的無特定順序)