3.5.5. Взаимодействие с устаревшим кодом

Множество программ С++ было написано до появления стандартной библиотеки, поэтому они не используют библиотечные типы string и vector. Кроме того, многие программы С++ взаимодействуют с программами, написанными на языке С или других языках, которые не могут использовать библиотеку С++. Следовательно, программам, написанным на современном языке С++, вероятно, придется взаимодействовать с кодом, который использует символьные строки в стиле С и/или массивы. Библиотека С++ предоставляет средства, облегчающие такое взаимодействие.

Совместное использование библиотечных строки строк в стиле С

В разделе 3.2.1 была продемонстрирована возможность инициализации строки класса string строковым литералом:

string s("Hello World"); // s содержит Hello World

В общем, символьный массив с нулевым символом в конце можно использовать везде, где используется строковый литерал.

• Символьный массив с нулевым символом в конце можно использовать для инициализации строки класса string или присвоения ей.

• Символьный массив с нулевым символом в конце можно использовать как один из операндов (но не оба) в операторе суммы класса string или как правый операнд в составном операторе присвоения (+=) класса string.

Однако нет никакого простого способа использовать библиотечную строку там, где требуется строка в стиле С. Например, невозможно инициализировать символьный указатель объектом класса string. Тем не менее класс string обладает функцией-членом c_str(), зачастую позволяющей выполнить желаемое.

char *str = s; // ошибка: нельзя инициализировать char* из string

const char *str = s.c_str(); // ok

Имя функции c_str() означает, что она возвращает символьную строку в стиле С. Таким образом, она возвращает указатель на начало символьного массива с нулевым символом в конце, содержащим те же символы, что и строка. Тип указателя const char* не позволяет изменять содержимое массива.

Допустимость массива, возвращенного функцией c_str(), не гарантируется. Любое последующее использование указателя s, способное изменить его значение, может сделать этот массив недопустимым.

Если программа нуждается в продолжительном доступе к содержимому массива, возвращенного функцией c_str(), то следует создать его копию.

Использование массива для инициализации вектора

В разделе 3.5.1 упоминалось о том, что нельзя инициализировать встроенный массив другим массивом. Инициализировать массив из вектора также нельзя. Однако можно использовать массив для инициализации вектора. Для этого необходимо определить адрес первого подлежащего копированию элемента и элемента, следующего за последним.

int int_arr[] = {0, 1, 2, 3, 4, 5};

// вектор ivec содержит 6 элементов, каждый из которых является

// копией соответствующего элемента массива int_arr

vector<int> ivec(begin(int_arr), end(int_arr));

Два указателя, используемые при создании вектора ivec, отмечают диапазон значений, используемых для инициализации его элементов. Второй указатель указывает на следующий элемент после последнего копируемого. В данном случае для передачи указателей на первый и следующий после последнего элементы массива int_arr использовались библиотечные функции begin() и end() (см. раздел 3.5.3). В результате вектор ivec содержит шесть элементов, значения которых совпадают со значениями соответствующих элементов массива int_arr.

Определяемый диапазон может быть также подмножеством массива:

// скопировать 3 элемента: int_arr[1], int_arr[2], int_arr[3]

vector<int> subVec(int_arr + 1, int_arr + 4);

Этот код создает вектор subVec с тремя элементами, значения которых являются копиями значений элементов от intarr[1] до intarr[3].

Совет. Используйте вместо массивов библиотечные типы

Указатели и массивы на удивление сильно подвержены ошибкам. Частично проблема в концепции: указатели используются для низкоуровневых манипуляций, в них очень просто сделать тривиальные ошибки. Другие проблемы возникают из-за используемого синтаксиса, особенно синтаксиса объявлений.

Упражнения раздела 3.5.5

Упражнение 3.41. Напишите программу, инициализирующую вектор значениями из массива целых чисел.

Упражнение 3.42. Напишите программу, копирующую вектор целых чисел в массив целых чисел.