C ++ вектор доступа за пределами размера () и под емкостью () - PullRequest
0 голосов
/ 12 декабря 2018

Безопасно ли получить доступ к векторным data()[i] для индексов i за пределами векторных size() и по векторным capacity()?

Вот мои рассуждения:

a) Согласно cplusplus , capacity() - это «размер дискового пространства, выделенного в данный момент для вектора», что заставляет меня думать, что ответ на мой вопрос YES, но тогда

b)Использование reserve() и доступ data за пределами вектора size() должны быть безопасными, поскольку согласно cplusplus , reserve() "заставляет контейнер перераспределять свое хранилище, увеличивая его емкость до n", но затем

c) Тема Stackoverflow противоречит утверждению b) выше

Так что я озадачен и ищу ответ.

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Нет, это небезопасно , потому что §23.3.6.4 ИСО / МЭК 14882: 2014 гласит

векторных данных ... Возвращает: Указатель такой, что [data (), data () + size ()) - допустимый диапазон.

Таким образом, по стандарту все, что находится за пределами size(), не определено, что означает так называемое неопределенное поведение ,что, как все подтвердят, является чем-то очень небезопасным.

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

0 голосов
/ 12 декабря 2018

Недействительно для доступа data()[n], если n >= size().За [vector.data] std::vector::data

Возвращает: Указатель такой, что [data(), data() + size()) является допустимым диапазоном.Для непустого вектора: data() == addressof(front()).

Таким образом, допустим только доступ к data со значением в диапазоне [0, size()).


Обычно память между data() + size() - 1 и data + capacity() неинициализируется.Если вы читаете из этой неинициализированной памяти, это неопределенное поведение.Если у вас есть объект, который имеет нетривиальную инициализацию, вы даже не можете присвоить ему значение, так как на самом деле в этом месте нет объекта, только место для него.Возможно, вы могли бы сойти с рук в неинициализированном диапазоне, но вы нарушаете контракт с std::vector, и это может вызвать гнев;)

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