Отредактировано после комментария underscore_d.
Описание того, как функции реализованы в VS2015
VS2015 CTP6
Это диалоговое окно ошибки существует только в режиме отладки, когда определено #if _ITERATOR_DEBUG_LEVEL == 2
. В режиме RELEASE у нас нет проблем. Мы получаем текущее значение на return (*(this->_Myfirst() + _Pos)
, поэтому size
значение не требуется:
reference operator[](size_type _Pos)
{ // subscript mutable sequence
#if _ITERATOR_DEBUG_LEVEL == 2
if (size() <= _Pos)
{ // report error
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}
#elif _ITERATOR_DEBUG_LEVEL == 1
_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
#endif /* _ITERATOR_DEBUG_LEVEL */
return (*(this->_Myfirst() + _Pos));
}
Если мы увидим в исходном коде вектора, то обнаружим, что разница между resize
и reserve
заключается только в изменении значения this->_Mylast()
в функции resize()
.
reserve()
звонки _Reallocate
.
resize()
вызывает _Reserve
, который вызывает _Reallocate
, а затем resize()
также изменяет значение this->_Mylast()
: this->_Mylast() += _Newsize - size();
, которое используется в расчете size
(см. Последнюю функцию)
void resize(size_type _Newsize)
{ // determine new length, padding as needed
if (_Newsize < size())
_Pop_back_n(size() - _Newsize);
else if (size() < _Newsize)
{ // pad as needed
_Reserve(_Newsize - size());
_TRY_BEGIN
_Uninitialized_default_fill_n(this->_Mylast(), _Newsize - size(),
this->_Getal());
_CATCH_ALL
_Tidy();
_RERAISE;
_CATCH_END
this->_Mylast() += _Newsize - size();
}
}
void reserve(size_type _Count)
{ // determine new minimum length of allocated storage
if (capacity() < _Count)
{ // something to do, check and reallocate
if (max_size() < _Count)
_Xlen();
_Reallocate(_Count);
}
}
void _Reallocate(size_type _Count)
{ // move to array of exactly _Count elements
pointer _Ptr = this->_Getal().allocate(_Count);
_TRY_BEGIN
_Umove(this->_Myfirst(), this->_Mylast(), _Ptr);
_CATCH_ALL
this->_Getal().deallocate(_Ptr, _Count);
_RERAISE;
_CATCH_END
size_type _Size = size();
if (this->_Myfirst() != pointer())
{ // destroy and deallocate old array
_Destroy(this->_Myfirst(), this->_Mylast());
this->_Getal().deallocate(this->_Myfirst(),
this->_Myend() - this->_Myfirst());
}
this->_Orphan_all();
this->_Myend() = _Ptr + _Count;
this->_Mylast() = _Ptr + _Size;
this->_Myfirst() = _Ptr;
}
void _Reserve(size_type _Count)
{ // ensure room for _Count new elements, grow exponentially
if (_Unused_capacity() < _Count)
{ // need more room, try to get it
if (max_size() - size() < _Count)
_Xlen();
_Reallocate(_Grow_to(size() + _Count));
}
}
size_type size() const _NOEXCEPT
{ // return length of sequence
return (this->_Mylast() - this->_Myfirst());
}
Проблемы
Но существуют некоторые проблемы с reserve
:
end()
будет равно begin()
23.2.1 Общие требования к контейнерам
5
end()
возвращает итератор, который является последним значением для контейнера.
iterator end() _NOEXCEPT
{ // return iterator for end of mutable sequence
return (iterator(this->_Mylast(), &this->_Get_data()));
}
т.е. _Mylast()
будет равно _Myfirst()
- at () сгенерирует исключение out_of_range.
23.2.3 Контейнеры последовательности
17
Функция-член at () обеспечивает доступ с проверкой границ к элементам контейнера. at () выбрасывает out_of_range, если n> = a.size ().
- в отладчике VisualStudio мы можем видеть векторные значения, когда размер не равен 0
с resize
:
с reserve
и настройкой вручную #define _ITERATOR_DEBUG_LEVEL 0
: