Массивы против векторов: вводные сходства и различия

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

Массив

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

- Справочник по С++ Pocket

Vector

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

- С++ Cookbook

Ответ 1

массивы:

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

std::vector:

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

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

Ответ 2

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

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

Ответ 3

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

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);
...

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