Доступ к необработанному указателю после std::vector:: резервный сейф?

Это довольно надуманный, но следующий код "безопасен" (т.е. гарантированно не вызывает ошибку сегментации):

std::vector<int> vec(1); // Ensures that &vec[0] is valid
vec.reserve(100);
memset(&vec[0], 0x123, sizeof(int)*100); // Safe?

Я понимаю, что это уродливо - мне только интересно узнать, технически ли это безопасно, а не "красиво". Я предполагаю, что его единственным использованием может быть игнорирование значений, хранящихся за пределами данного индекса.

Внимание! Как я могу получить адрес буфера, выделенного vector:: reserve()?, охватывает ту же тему, но меня больше интересует, если это безопасно, и если это подводные камни, делающие это.

EDIT: Исходный код был неправильным, заменил оригинал memcpy на memset.

Ответ 1

Нет, это не безопасно.

После a reserve(), вектор гарантированно не перераспределяет хранилище до достижения capacity().

Однако стандарт не говорит, что векторная реализация может выполнять с хранилищем между size() и capacity(). Возможно, это может быть использовано для некоторых внутренних данных - кто знает? Возможно, адресное пространство просто зарезервировано и не отображено в реальном ОЗУ?

Доступ к элементам за пределами [0..размер] - это поведение undefined. Для этого может быть какая-то аппаратная проверка.

Ответ 2

Вектор-перераспределение делает недействительными указатели существующих, ссылки и т.д. Резерв может запускать перераспределение (23.3.6.2, [vector.capacity]), но вы берете адрес первый элемент после возможного перераспределения (что в этом случае, вероятно, не произойдет вообще, но это помимо точки). Поэтому я не вижу проблем с кодом.

Ответ 3

Прежде всего обратите внимание, что ваш memset обрезает 0x123 в один байт и напишет это, не записывая четырехбайтовый шаблон.

Тогда не делайте этого, просто используйте контейнер: std::vector<int> vec(100, whatever_value_you_want);

Однако для ответа на вопрос он может работать специально для типов POD, если компилятор не использует выделенное пространство для чего-либо. Конечно, если кто-либо называет resize, insert, push_back и т.д., Он сдует все, что вы уже записали в память, и размер вектора также будет неправильным. Там просто нет причин писать такой код.