Хотя в большинстве реализаций для string
также используется непрерывный блок памяти, это не гарантируется стандартом, так что никогда не используйте адрес символа в строке, считая его указателем на все содержимое строки. Хорошая новость заключается в том, что функция string::c_str
всегда возвращает строку в стиле С с завершающим нулевым символом (string::data
также возвращает указатель на непрерывный блок памяти, но не гарантирует наличия завершающего нулевого символа).
Когда вы передаете указатель на данные объекта v
типа vector
, код на языке С может как читать, так и записывать элементы v
; однако он не должен выходить за границы данных. Хорошо продуманный API на языке С должен получать наряду с указателем либо максимальное количество объектов (до v.size()
), либо указатель на элемент, следующий за последним (&*v.begin()+v.size()
).
Если у вас есть контейнер объектов типа T
, отличный от vector
или string
, и вы хотите передать его содержимое (или заполнить его) функции API на другом языке программирования, которая ожидает указатель на массив объектов типа T
, скопируйте содержимое контейнера в (или из) vector
, который может непосредственно сообщаться с такими функциями.
79. Храните в контейнерах только значения или интеллектуальные указатели
Храните к контейнерах объекты-значения. Контейнеры полагают, что их содержимое имеет тип значения, включая непосредственно хранящиеся значения, интеллектуальные указатели и итераторы.
Наиболее распространенное использование контейнеров — для непосредственного хранения значений (например, vector
). В случае контейнеров указателей, если контейнер владеет объектами, на которые указывает, то лучше использовать контейнер интеллектуальных указателей со счетчиком ссылок (например, list
); в противном случае можно выбрать контейнер обычных указателей (например, list
) или иных значений, подобных указателям — таких как итераторы (например, list
).
auto_ptr
не являются объектами-значениями из-за своей семантики передачи владения при копировании. Использование контейнера объектов auto_ptr
(например, vector
) должно привести к ошибке компиляции. Но даже в случае успешной компиляции никогда не пишите такой код — вместо этого вам следует использовать контейнер интеллектуальных указателей shared_ptr
.
container
. Альтернативой является хранение прокси-объектов, невиртуальные функции которых передают вызовы соответствующим виртуальным функциям реальных объектов.
DatabaseLock
или TcpConnection
), их следует хранить опосредованно, с использованием интеллектуальных указателей (например, container
или container
).
map
, но некоторые Thing
не имеют связанных с ними объектов Widget
, можно использовать map
.
MainContainer::iterator
(которые являются значениями).
80. Предпочитайте push_back
другим способам расширения последовательности