Вход/Регистрация
Стандарты программирования на С++. 101 правило и рекомендация
вернуться

Александреску Андрей

Шрифт:

Вот некоторые из причин, по которым массивам в стиле С следует предпочесть стандартные средства С++.

• Они автоматически управляют собственной памятью. Больше не требуется никаких фиксированных буферов с размером "большим, чем любая разумная длина" ("бомба с часовым механизмом" — вот как правильно прочесть это определение), или сплошных перераспределений памяти при помощи

reallос
и соответствующих обновлений указателей.

• У них богатый интерфейс. Вы легко и выразительно можете реализовать сложную функциональность.

• Они совместимы с моделью памяти в С.

vector
и
string::c_str
могут быть переданы функциям API на языке С. В частности, в С++
vector
служит "переходником" к С и другим языкам программирования (см. рекомендации 76 и 78).

• Они обеспечивают расширенные возможности проверки. Стандартные средства позволяют реализовать (в отладочном режиме) итераторы и операторы индексирования, которые способны выявить большой класс ошибок памяти. Многие из современных реализаций стандартной библиотеки предоставляют такие отладочные возможности — воспользуйтесь ими! (См. рекомендацию 83.)

• Они практически не снижают эффективность ваших программ. В классах

vector
и
string
при выборе между эффективностью и безопасностью решение принимается в пользу эффективности (естественно, не в отладочном режиме). Тем не менее, стандартные средства оказываются гораздо лучшей платформой для создания безопасных компонентов, чем обычные массивы и указатели.

• Они стимулируют оптимизацию. Современные реализации стандартной библиотеки включают оптимизации, о которых многие из нас просто никогда бы и не подумали.

Применение массива может быть оправданно, когда его размер фиксирован на стадии компиляции (например,

float[3]
для трехмерной точки; переход к четвертому измерению все равно потребует перепроектирования программы).

Ссылки

[Alexandrescu01а] • [Dewhurst03] §13, §60, §68 • [Meyers01] §13, §16 • [Stroustrup00] §3.5-7, §5.3, §20.4.1, §C.7 • [Sutter00] §36

78. Используйте

vector
(и
string::c_str
) для обмена данными с API на других языках

Резюме

vector
и
string::c_str
служат шлюзом для сообщения с API на других языках. Однако не полагайтесь на то, что итераторы являются указателями; для получения адреса элемента, на который ссылается
vector<T>::iterator iter
, используйте выражение
&*iter
.

Обсуждение

vector
(в первую очередь) и
string::c_str
и
string::data
(во вторую) представляют собой наилучшие способы обмена данными с API на других языках вообще и с библиотеками на С в частности.

Данные

vector
всегда хранятся последовательно, так что получение адреса первого элемента вектора дает указатель на его содержимое. Используйте
&*v.begin
,
&v[0]
или
&v.front
для получения указателя на первый элемент
v
. Для получения указателя на n-й элемент вектора лучше сначала провести арифметические вычисления, а затем получить адрес (например,
&v.begin[n]
или
&v[n]
) вместо получения указателя на начало данных с последующим применением арифметики указателей (например,
(&v.front)[n]
). Это связано с тем, что в первом случае в отладочной реализации выполняется проверка на доступ к элементу за пределами
v
(см. рекомендацию 83).

Нельзя полагаться на то, что

v.begin
возвращает указатель на первый элемент или, в общем случае, что итераторы вектора являются указателями. Хотя некоторые реализации STL определяют
vector<T>::iterator
как обычный указатель
T*
, итераторы могут быть (и все чаще так оно и есть) полноценными типами (еще раз см. рекомендацию 83).

Хотя в большинстве реализаций для

string
также используется непрерывный блок памяти, это не гарантируется стандартом, так что никогда не используйте адрес символа в строке, считая его указателем на все содержимое строки. Хорошая новость заключается в том, что функция
string::c_str
всегда возвращает строку в стиле С с завершающим нулевым символом (
string::data
также возвращает указатель на непрерывный блок памяти, но не гарантирует наличия завершающего нулевого символа).

Когда вы передаете указатель на данные объекта

v
типа
vector
, код на языке С может как читать, так и записывать элементы
v
; однако он не должен выходить за границы данных. Хорошо продуманный API на языке С должен получать наряду с указателем либо максимальное количество объектов (до
v.size
), либо указатель на элемент, следующий за последним (
&*v.begin+v.size
).

Если у вас есть контейнер объектов типа

T
, отличный от
vector
или
string
, и вы хотите передать его содержимое (или заполнить его) функции API на другом языке программирования, которая ожидает указатель на массив объектов типа
T
, скопируйте содержимое контейнера в (или из)
vector<T>
, который может непосредственно сообщаться с такими функциями.

  • Читать дальше
  • 1
  • ...
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: