2012-02-28 4 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 
    //... 
} 

Право знаю, что все мои векторы хранятся в куче, верно?

Какой из них более полезен в соответствии с управлением памятью?

ответ

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_size и vector_capacity, а объект распределителя, alloc, все будут созданы на стек (наряду с распределением любой дополнительной памяти, необходимой для заполнения и выравнивания структуры).

Однако сам вектор выделяет память на кучу, на которую этот указатель buffer сохранит свой базовый адрес. Это всегда будет в куче и будет содержать фактическое содержимое вектора, как мы думаем о них.

Это еще более эффективно, чем это:

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

... так как это повлечет за собой выделение кучи/открепление для самого (в том числе его членов данных) вектора в дополнение к вектору памяти сама выделяет для его внутреннее содержимое (буфер). Он также вводит дополнительный уровень косвенности.

Теперь, если мы имеем вектор Somethings (вектор вектора или что-нибудь еще):

vector<Something> v; 

Эти Something случаи всегда будут выделяться в непрерывный буфер кучи, так как они будут находиться в динамически распределяемой блоки памяти, которые вектор создает и разрушает внутри.

+0

очень хорошее объяснение. Большое спасибо.. – emreakyilmaz

3

В векторе <> все данные, хранящиеся в куче И я думаю, вы должны просто использовать

vector< vector<double> > something; 
+0

Фактическое совокупное содержимое вектора, да. Но векторный объект обычно содержит некоторые дополнительные указатели или интегралы, и те, вместе с самим векторным объектом, могут существовать в стеке, как указывает ваш код. – stinky472

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/). –

+0

копия elision здесь не кажется актуальной, так как tere не копирует в этом примере –

0

Ответы Joe и 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] 
               ... 

(конечно, не существует какой-либо особое упорядочивания блоков в куче)

Смежные вопросы