Доступ к необработанному указателю после std :: vector :: Reserve безопасен? - PullRequest
6 голосов
/ 22 ноября 2011

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

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

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

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

РЕДАКТИРОВАТЬ: оригинальный код был неправильным, заменил оригинальный memcpy на memset.

Ответы [ 3 ]

16 голосов
/ 22 ноября 2011

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

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

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

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

2 голосов
/ 22 ноября 2011

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

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

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

2 голосов
/ 22 ноября 2011

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

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