2016-01-16 2 views
6

Я изучаю векторы, и я запутался, как массив копирования thevector здесьЧто означает «один-последний-последний элемент» в векторах?

double p[] = {1, 2, 3, 4, 5}; 
std::vector<double> a(p, p+5); 

Я также знаю std::vector<double> a(3,5); означает `потесниться для 3 и инициализировать их 5. Как вышеприведенный код будет работать?

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

Понимание второй точки имеет решающее значение при работе с векторами или любых других стандартных контейнеров. Управляемая последовательность всегда , выраженная в терминах [first, one-last-last) - не только для ctors, но и также для каждой функции, которая работает с рядом элементов.

Я не знаю, что означает [first, one-past-last)? Я знаю математически, но не знаю, почему/как вектор копирует массив таким образом?

Под редакцией

другой связанный с этим вопрос

Функция член end() возвращает итератор, что "точки" к one-past-the-last-element в последовательности. Обратите внимание, что разыменование итератора , возвращенного end(), является незаконным и имеет неопределенные результаты.

Не могли бы вы объяснить это one-past-the-last-element что это? и почему?

+0

std :: vector имеет перегруженные конструкторы, поэтому код выше кода работает. и '[first, one-last-last]' означает, что первый элемент включен и исключен один-последний-последний, который является указателем на последний элемент + 1 –

+0

@AngelusMortis, но почему? и я также отредактировал мой вопрос. перезагрузить. – UnKnown

+0

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

ответ

11

Никогда не разыскивайте end() или rend() из контейнеров STL, так как они не указывают на действительные элементы.
Этот снимок может помочь вам визуализировать это.

enter image description here

Преимущество в полуоткрытом диапазона:
1. Обработка пустых диапазонов возникают, когда начинают() == конец()
2. Итерация по элементам может быть интуитивно сделано путем проверки пока итератор не будет равен end().

+1

(возможно, это был бы более ясным с 0-4 вместо 1-5 как inidices) – deviantfan

+1

@UnKnown Поскольку 'i ++' предположительно создает копию 'i' сначала, прежде чем увеличивать ее, а' ++ i' - нет. Это действительно не имеет значения в наши дни, потому что компиляторы могут легко оптимизировать это. –

+0

'1. Обработка пустых диапазонов происходит, когда begin() == end() 'вы можете исследовать, пожалуйста? – UnKnown

2

У конструктора std::vector несколько перегрузок.

Для std::vector<double> a(3,5); используется конструктор заливки:

explicit vector (size_type n); 
     vector (size_type n, const value_type& val, 
       const allocator_type& alloc = allocator_type()); 

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

double p[] = {1, 2, 3, 4, 5}; 
std::vector<double> a(p, p+5); 

использует другую перегрузку конструктора, а именно конструктор диапазон:

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

Это занимает итератор на начало коллекции и end() итератора и траверс и добавляет к vector до first == last.

Причина, почему end() реализуется как one-past-the-last-element происходит потому, что это позволяет реализации для проверки равенства, как:

while(first != last) 
{ 
    //savely add value of first to vector 
    ++first; 
} 
+0

+1 за лоп. Просто чтобы подтвердить. если последний конец без 'one-past', то 5 мог пропустить в моем массиве? – UnKnown

+0

@UnKnown Если ожидалось, что 'end()' не будет указывать 'one-past', тогда конструктор будет читать один за другим фактический массив, что-то нежелательное. –

+0

Можете ли вы дать мне ссылку, которая может очистить все мои вопросы или путаницу, связанные с этим? потому что я снова запутался в том, как contructor мог прочитать одно за фактическим массивом? – UnKnown

3

Сильно в сочетании с контейнерами (например, вектор, список, карта) является понятие итераторы. Итератор - это абстракция C++ указателя. То есть итератор указывает на объект внутри контейнера (или один за последним элементом), а разыменование итератора означает доступ к этому элементу.

Давайте, например, вектор из 4 элементов:

| 0 | 1 | 2 | 3 | | 
^  ^^
    |   | | 
    |   | one past the end (outside of the container elements) 
    |   last element   
    first element 

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

Диапазон указан [first, last) (включительно первый, исключительный последний). Вот почему вам нужен итератор до конца: указать диапазон, равный всему содержимому контейнера. Но поскольку этот итератор указывает за его пределы, это незаконно разыгрывать его.

0

Итераторы - это абстракция указателей.

Полуоткрытый интервал [a,b) определяется как все элементы x>=a и x<b. Преимущество этого заключается в том, что [a,a) четко определен и пустой для любых a.

Все, что может быть увеличено и сравнено, может определить полуоткрытый интервал. Таким образом, [ptr1,ptr2) - это элемент ptr1, затем ptr1+1, затем ptr1+2, пока не достигнете ptr2, но не включая ptr2.

Для итераторов это похоже - за исключением того, что мы не всегда имеем произвольный доступ. Поэтому мы говорим о next вместо +1.

Указатели по-прежнему считаются своего рода итератором.

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

Вы можете построить вектор из такого полуоткрытого диапазона. Он копирует элементы poimtrd в вектор.

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