77. Вместо массивов используйте vector
stringИзбегайте реализации абстракция массива посредством массивов в стиле С, арифметики указателей и примитивов управления памятью. Использование vector
string не только сделает проще вашу жизнь, но и позволит написать более безопасную и масштабируемую программу.Сегодня едва ли не основными вопросами при написании программного обеспечения являются вопросы безопасности и переполнения буфера. Ограничения, связанные с фиксированным размером массивов, доставляют немало беспокойства, даже если приложению удается остаться в рамках корректности. Все эти проблемы связаны с использованием старых средств С, таких как встроенные массивы, указатели и их арифметика, а также управление памятью вручную вместо таких высокоуровневых концепций, как буферы, векторы и строки.
Вот некоторые из причин, по которым массивам в стиле С следует предпочесть стандартные средства С++.
•
reallос и соответствующих обновлений указателей.•
•
vector и string::c_str могут быть переданы функциям API на языке С. В частности, в С++ vector служит "переходником" к С и другим языкам программирования (см. рекомендации 76 и 78).•
•
vector и string при выборе между эффективностью и безопасностью решение принимается в пользу эффективности (естественно, не в отладочном режиме). Тем не менее, стандартные средства оказываются гораздо лучшей платформой для создания безопасных компонентов, чем обычные массивы и указатели.•
Применение массива может быть оправданно, когда его размер фиксирован на стадии компиляции (например, float[3]
78. Используйте vector
string::c_str) для обмена данными с API на других языкахvector
string::c_str служат шлюзом для сообщения с API на других языках. Однако не полагайтесь на то, что итераторы являются указателями; для получения адреса элемента, на который ссылается vector::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()
vector::iterator как обычный указатель T*, итераторы могут быть (и все чаще так оно и есть) полноценными типами (еще раз см. рекомендацию 83).