вопрос про вектор в с ++ - PullRequest
8 голосов
/ 22 июня 2011

Я прочитал код, написанный на c ++, следующим образом:

#include <algorithm>
#include <iostream> 
#include <vector>

using namespace std;

int main() {
    int iarr[] = {30, 12, 55, 31, 98, 11, 41, 80, 66, 21};
    vector<int> ivector(iarr, iarr + 10);
}

в приведенном выше коде я передаю iarr и iarr+10 в ivector(iarr, iarr + 10), чтобы создать новый вектор, это правильный способ построения vector? Я проверил документ STL, там не упоминается, это разрешено?

а также, массив iarr содержит 10 элементов, я должен использовать ivector(iarr, iarr+9)?

Ответы [ 7 ]

12 голосов
/ 22 июня 2011

Да, это разрешено, и да, вы делаете это правильно.

Вы вызываете этот шаблонный конструктор:

template<class InputIterator>
   vector(
      InputIterator _First,
      InputIterator _Last
   );

Параметр шаблона InputIterator равен int* (это тип выражений iarr и iarr + 10).

Поскольку в документации указано, что _Last должен указывать на один элемент за пределами последнего в диапазоне, + 10 также является правильным для копирования всех 10 элементов в массиве (iarr + 9 указывает на последний элемент, iarr + 10 указывает на один за последним элементом).

5 голосов
/ 22 июня 2011

Простой помощник для массивов:

template <typename T, size_t N>
size_t size(T(&)[N]) { return N; }

template <typename T, size_t N>
T* begin(T(&array)[N]) { return array; }

template <typename T, size_t N>
T* end(T(&array)[N]) { return array + N; }

Теперь вы можете написать:

int main() {
  int const arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
  std::vector<int> vec(begin(arr), end(arr));
}

И не беспокойтесь о размере массива, он будет вычислен автоматически.

3 голосов
/ 22 июня 2011

Да, это конструктор std::vector. Вот этот:

template <class InputIterator>
     vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );

Требуются два итератора (в вашем случае указатели), один в начало, а другой в конец последовательности элементов, которые должны инициализировать вектор. Последний параметр является необязательным, и он вам не нужен, если вы не используете пользовательские распределители.

Итератор до конца должен быть один за последним элементом, который вы хотите включить. Итак, если вы хотите, чтобы все элементы от iarr[0] до iarr[9], вам нужно передать в iarr + 10.

1 голос
/ 22 июня 2011

Этот код действительно разрешен, если вы посмотрите, например, документацию здесь

template <class InputIterator>
vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );

Диапазон, заданный аргументами, соответствует обычному соглашению [first, last [, поэтому передача iarr + 10 правильна, если вы хотите скопировать весь массив

1 голос
/ 22 июня 2011

Распределение вектора осуществляется с помощью Iterators и исходного показанного iarr [].Есть десять элементов, и +10 - правильная итерация, потому что это один шаг после конца.Вот как работают векторы - он должен указывать на одну позицию за концом.Это копирование содержимого массива в вектор.Более ясно, что он использует этот шаблон для создания вектора:

template <class InputIterator> vector ( InputIterator first, 
InputIterator last, const Allocator& = Allocator() );

Конструктор итерации: выполняет итерацию между первым и последним, устанавливая копию каждой последовательности элементов в качестве содержимого контейнера.

0 голосов
/ 22 июня 2011

Да, последняя строка в функции main () вызывает конструктор std :: vector.Посмотрите здесь , чтобы увидеть все перегрузки векторных конструкторов.Третий используется здесь.Его параметры являются итераторами для типа шаблона (здесь используется аргумент шаблона int, поэтому итератор имеет тип int*).Второй аргумент - это итератор, который указывает на первый элемент последовательности, который не будет скопирован в вектор.

0 голосов
/ 22 июня 2011

Да, это разрешено, и ivector будет содержать 10 элементов. И нет, это не должно быть 9, потому что конечный итератор должен быть на один шаг после конца . Если вы знаете, что это за диапазоны, этот диапазон будет представлен этим диапазоном: [beginning, end). То есть, включите первый и идите вверх, но не включайте последний.

Поскольку STL (стандартная библиотека C ++ cough ) - это все шаблоны, все, что поддерживает операторы ++ и * (оператор разыменования), может быть передано в качестве итераторов в конструктор вектора. Это свойство удивительно заставляет работать один и тот же код как для указателей, так и для vector итераторов. Стандартный дизайн библиотеки в лучшем виде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...