Массивы против векторов: общие черты и различия [закрыто]

111

В чем разница между массивом и вектором в C ++? Примером различий могут быть библиотеки, символика, способности и т. Д.

массив

Массивы содержат определенное количество элементов определенного типа. Чтобы компилятор мог зарезервировать необходимый объем пространства при компиляции программы, вы должны указать тип и количество элементов, которые будет содержать массив при его определении. Компилятор должен иметь возможность определить это значение при компиляции программы. После определения массива вы используете идентификатор массива вместе с индексом для доступа к определенным элементам массива. [...] массивы имеют нулевой индекс; то есть первый элемент имеет индекс 0. Эта схема индексации указывает на тесную взаимосвязь в C ++ между указателями и массивами и правилами, которые язык определяет для арифметики указателей.

- Карманный справочник C ++

Вектор

Вектор - это последовательность объектов динамического размера, обеспечивающая operator[]произвольный доступ в стиле массива . Функция-член push_backкопирует свои аргументы через конструктор копирования, добавляет эту копию в качестве последнего элемента в векторе и увеличивает ее размер на единицу.pop_backделает прямо противоположное, удаляя последний элемент. Вставка или удаление элементов с конца вектора требует амортизированного постоянного времени, а вставка или удаление из любого другого места занимает линейное время. Это основы векторов. Есть еще много чего. В большинстве случаев вектор должен быть вашим первым выбором, а не массивом в стиле C. Прежде всего, они имеют динамический размер, что означает, что они могут расти по мере необходимости. Вам не нужно проводить всевозможные исследования, чтобы определить оптимальный статический размер, как в случае массивов C; вектор увеличивается по мере необходимости, и при необходимости его размер можно увеличивать или уменьшать вручную. Во-вторых, векторы предлагают проверку границ с помощью atфункции-члена (но не с помощьюoperator[]), чтобы вы могли что-то сделать, если вы ссылаетесь на несуществующий индекс, вместо того, чтобы просто наблюдать за сбоями вашей программы или, что еще хуже, продолжать выполнение с поврежденными данными.

- Поваренная книга C ++

Транкот
источник
Основная разница: есть цели, для которых вектор является хорошим выбором.
Джерри Коффин,
1
«исчерпывающий» и «согласованный» ортогональны. То есть не только одно не подразумевает другого, но они даже не в одном масштабе.
Гонки легкости на орбите
2
Я очень расстраиваюсь из-за людей, которые задают вопросы, которые являются именно той информацией, которую я ищу. Это случается слишком часто.
Роберт Тамлин

Ответы:

142

массивы:

  • являются встроенной конструкцией языка;
  • почти без изменений от C89;
  • предоставить только непрерывную, индексируемую последовательность элементов ; никаких наворотов;
  • имеют фиксированный размер; вы не можете изменить размер массива в C ++ (если это не массив POD и он выделен с помощью malloc);
  • их размер должен быть константой времени компиляции, если они не распределяются динамически;
  • они занимают свое место для хранения в зависимости от области, в которой вы их декларируете;
  • если они выделяются динамически, вы должны явно освободить их;
  • если они выделяются динамически, вы просто получаете указатель и не можете определить их размер; в противном случае вы можете использовать sizeof(отсюда и распространенная идиома sizeof(arr)/sizeof(*arr), которая, однако, не работает при случайном использовании с указателем);
  • автоматически переходят в указатели в большинстве ситуаций; в частности, это происходит при передаче их в функцию, которая обычно требует передачи отдельного параметра для их размера;
  • не может быть возвращен из функции;
  • не может быть скопирован / назначен напрямую;
  • динамические массивы объектов требуют конструктора по умолчанию, поскольку все их элементы должны быть сконструированы в первую очередь;

std::vector:

  • это шаблонный класс;
  • является только конструкцией C ++;
  • реализован в виде динамического массива ;
  • динамично растет и сжимается;
  • автоматически управлять своей памятью, которая освобождается при уничтожении;
  • могут быть переданы / возвращены из функций (по значению);
  • может быть скопирован / назначен (это выполняет глубокую копию всех сохраненных элементов);
  • не распадается на указатели, но вы можете явно получить указатель на их данные ( &vec[0]гарантированно работает должным образом);
  • всегда содержит вместе с внутренним динамическим массивом его размер (сколько элементов в настоящее время хранится) и емкость (сколько элементов может быть сохранено в текущем выделенном блоке);
  • внутренний динамический массив не размещается внутри самого объекта (который просто содержит несколько «бухгалтерских» полей), а распределяется динамически распределителем, указанным в соответствующем параметре шаблона; по умолчанию память получает из бесплатного хранилища (так называемой кучи), независимо от того, где размещен фактический объект;
  • по этой причине они могут быть менее эффективными, чем «обычные» массивы для небольших, недолговечных локальных массивов;
  • при перераспределении объекты копируются (перемещаются, в C ++ 11);
  • не требует конструктора по умолчанию для сохраняемых объектов;
  • лучше интегрирован с остальной частью так называемого STL (он предоставляет методы begin()/ end(), обычные STL typedef, ...)

Также рассмотрим «современную альтернативу» массивам - std::array; Я уже описал в другом ответе разницу между std::vectorи std::array, вы можете взглянуть на это.

Маттео Италия
источник
1
Спасибо, @MatteoItalia. Ссылка или две было бы неплохо.
Trancot
1
@Trancot: подойдет любая хорошая книга по C ++.
Маттео Италия
6
@Trancot: Я действительно не могу дать вам намного лучшие ссылки - различия, выделенные в этом посте, происходят из множества разных частей Стандарта, и их лучше понять с помощью хорошего руководства по C ++.
Matteo Italia
Было бы здорово привести пример такого обширного описания!
carloswm85
26

Я добавлю, что массивы - это очень низкоуровневые конструкции в C ++, и вы должны стараться держаться от них как можно дальше при «изучении веревок» - это рекомендует даже Бьярн Страуструп (он разработчик C ++).

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

Джон Келлен
источник
1
Интерфейс прикладной программы: ( en.wikipedia.org/wiki/API ). Это набор точек входа в программный объект (пакет, библиотека, операционная система). Некоторые API-интерфейсы будут иметь точки входа, такие как strcat (char * dst, char * src), где dst и src обрабатываются как массивы символов (даже если подпись функции подразумевает указатели на символы).
Джон Келлен
11

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

int myArray[100];
myArray[0]=1;
myArray[1]=2;
myArray[2]=3;

для векторов вы просто объявляете его и добавляете элементы

vector<int> myVector;
myVector.push_back(1);
myVector.push_back(2);
myVector.push_back(3);
...

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

Николас Браун
источник