2015-09-20 5 views
4

У меня есть два вопроса относительно векторов.C++ - Как хранятся многомерные векторы?

  1. Допустим, у меня есть многомерный вектор следующим образом: -

    vector< vector<int> > A;

    Тогда A[0], A[1] и т.д. являются векторами. Как хранятся векторы в A? I означает, какая информация об векторах A[0] и A[1] хранится в A? И перераспределение памяти отдельных векторов, таких как A[2] , вызывает перераспределение A?

  2. Во-вторых, я попытался увидеть, как адреса вектора изменяются с перераспределением. Я использовал следующий код: -

Код:

vector<int> A; 
int* x ; 
int* y ; 

vector<int>* ad; 
vector<int>* bd; 

for(int i = 0 ; i < 10000; i++){ 

    A.push_back(i); 
    if(i == 2){ 
     y = &A[0]; 
     ad = &A; 
    } 
    x = &A[0]; 
    bd = &A;  

} 

Я обнаружил, что, адрес для A не меняется, даже если адрес для A[0] изменений. Этого следует ожидать, поскольку векторы работают в фоновом режиме, используя new и delete. Но мой вопрос в том, сколько информации (или какой информации) о векторе хранится в адресе &A (с учетом адреса &A не изменяется). Это вопрос, который я имею и в отношении первого вопроса.

Я пытаюсь лучше понять, как работают векторы по умолчанию.

+1

Это довольно просто: 'станд :: вектор ' 'содержит объекты x', независимо от типа' x' (с возможным исключением 'std :: vector '.) – juanchopanza

+0

'Что хранится в A' Элементы типа' vector ', конечно, вид' A' - это 'vector >' (и не 'vector ' для некоторого типа 'T'). 'Я подозреваю, что он хранит указатели' И на чем вы основали подозрение? –

+0

STL - это не то же самое, что и стандартная библиотека C++. –

ответ

4

сколько информации (или какая информация) о векторе хранится в адресе &A

Вы правы, предполагая, что данные для вектора хранятся отдельно от самого векторного объекта - как правило, , в динамической памяти.

Три вещи вектор сам объект должен знать, являются

  • местоположении данных вектора в - нам это нужно выполнить оператор [],
  • Размер выделяемых в настоящее время - мы нужно знать, когда выращивать массив, и
  • Число элементов, фактически помещенных в вектор - нам нужно это знать, где push_back, и что вернуть с size().

Возможны различные реализации, сохраняющие всего лишь один указатель в самом векторном объекте. Однако типичная реализация сохраняет указатель на начало выделенного блока, указатель на конец активной части выделенного блока и указатель на конец выделенного блока.

+0

Итак, если у меня есть вектор вектора int, как A (в вопросе 1), его память не будет перераспределена, если я добавлю элементы в одномерные векторы. Но если я добавлю новый один-й вектор в A, это может потребоваться перераспределение памяти. У меня были эти вопросы, потому что этот метод хранения сильно отличается по сравнению с многомерными массивами. (Я много использовал массивы, но не векторы) – ameyask86

+0

@ ameyask86 Вы правы, добавление к внутренним векторам не приводит к перераспределению внешнего вектора. Модель хранения 2D-массивов против векторов векторов очень различна. Бывают ситуации, когда это становится важным - например, при оптимизации стратегии доступа к кеш-памяти: программа с длинным узким 2D-массивом может получить значительно лучшую производительность, чем программа с вектором векторов того же размера. – dasblinkenlight

2

Что касается вектора адрес: Адрес A не меняется, а не потому, что А является вектором, а потому, что изменения адреса без каких-либо переменной в то время как функция, где вы определяете его (или, точнее, конкретный вызов вашей функция). Я думаю, что вы можете ввести в заблуждение адрес A (ad, bd в вашем примере) с адресом того, что A использует для хранения элементов вектора (x и y, по существу, в вашем примере). Векторы распределяют, де-распределяют или перераспределяют память.

Обратите внимание, что A[0] не является переменной, которую вы определили. Это результат вызова A.operator[]; поэтому его местонахождение может изменение.

Относительно того, что на самом деле хранится в &A: Это довольно сложно. Вам нужно будет посмотреть заголовочный файл vector в вашей установке на C++. Или, возможно, было бы лучше посмотреть на webpage for std::vector по телефону cppreference.com. Заметьте, что существует множество шаблонов, а также некоторые подклассы и некоторые явные специализированные шаблоны, так что, как я уже сказал, сложны. Возможно, вам захочется пересмотреть вопрос о том, действительно ли вы хотите посмотреть под капотом, чтобы понять, как этот контейнер работает как общее правило, или достаточно ли сейчас общедоступных методов класса и sizeof().

+0

Да, но адрес A [0] изменен. Я где-то, где A [0] был изменен, я думаю, это из-за перераспределения. – ameyask86

+0

Я хотел знать, хранит ли он фактические элементы в & A, которые я сейчас не думаю, что это так. Моя основная проблема заключается в том, что если в многомерном векторе A (вопрос 1) я вставляю элементы в вектор A [2], будет ли какое-либо перераспределение памяти в A? (в A [2] может быть перераспределение памяти. Но число векторов в A не изменилось, поэтому я подтверждал, будет ли перераспределение в A). – ameyask86

+0

@Blastfurnace, у меня была эта забота, потому что. В моем приложении у меня есть n 1-d векторов, каждый из которых может динамически меняться во время выполнения. Но число n фиксировано. Поэтому я подумываю использовать для этого 2-й вектор. (ранее я был смущен тем, следует ли мне хранить указатели на n 1-d векторы вместо этого из-за страха перераспределения в родительском векторе из-за перераспределения в дочернем векторе). – ameyask86

0

Я новичок в C++ и STL, поэтому я просто тестирую вашу проблему с помощью некоторых простых кодов; во-первых, у меня есть эти коды:

std::vector<int> tmp; 
std::cout << sizeof(tmp) << " " << tmp.size() << " " << tmp.capacity << std::endl; 

выход является:

12 0 0 

Затем, мы вводим некоторые значения в вектор

for(int i = 0; i != 10; ++i) tmp.push_back(i); 
std::cout << sizeof(tmp) << " " << tmp.size() << " " << tmp.capacity << std::endl; 

выход

12 10 16 

затем , мы можем сделать вывод, что вектор просто удерживает указатель, поэтому результат sizeof() не изменился. Итак, ответ на ваш вопрос: push_back дочернего вектора не приведет к перераспределению родительского вектора (я не знаю, как выразить роль этих двух векторов). Есть некоторые простые коды:

std::vector<int> v1(10); 
std::vector<int> v2(10); 

int i; 
for(i = 0; i != 10; ++i) 
    v1[i] = i; 
for(i = 0; i != 10; ++i) 
    v2[i] = i; 

vv.push_back(v1); 
vv.push_back(v2); 

std::cout << "v1 capacity: " << v1.capacity() << " v1 size: " << v1.size() << std::endl; 
std::cout << "v2 capacity: " << v2.capacity() << " v2 size: " << v2.size() << std::endl; 
std::cout << "vv capacity: " << vv.capacity() << " vv size: " << vv.size() << std::endl; 

for(i = 10; i != 20; ++i) 
    v1.push_back(i); 
for(i = 10; i != 20; ++i) 
    v2.push_back(i); 

std::cout << "v1 capacity: " << v1.capacity() << " v1 size: " << v1.size() << std::endl; 
std::cout << "v2 capacity: " << v2.capacity() << " v2 size: " << v2.size() << std::endl; 
std::cout << "vv capacity: " << vv.capacity() << " vv size: " << vv.size() << std::endl; 

выход:

v1 capacity: 10 v1 size: 10 
v2 capacity: 10 v2 size: 10 
vv capacity: 2 vv size: 2 
v1 capacity: 20 v1 size: 20 
v2 capacity: 20 v2 size: 20 
vv capacity: 2 vv size: 2 
Смежные вопросы