Преобразование массива в вектор
Рассмотрим несколько методов преобразование из массива в std::vector. Так же рассмотрим преобразование QByteArray в std::vector и QVector. Для начала рассмотрим преобразования массива в std::vector
Объявим значения для преобразования:
using namespace std; vector<int> dataVec; int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; unsigned dataArraySize = sizeof(dataArray) / sizeof(int);
std::copy и back_inserter
// Копирование массива в вектор, используя back_inserter и метод copy std::copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
Описание функции:
copy (InputIterator first, InputIterator last, OutputIterator result);
Копирует элементы в диапазоне [first, last) в диапазон, начинающийся с результата. Функция возвращает итератор в конец целевого диапазона (который указывает на элемент, следующий за последним скопированным элементом). Диапазоны не должны перекрываться таким образом, чтобы результат указывал на элемент в диапазоне [first, last).
Описание параметров функции std::copy:
first, last
Итераторы в начальные и конечные позиции в последовательности, которые будут скопированы. Используемый диапазон — [first, last), который содержит все элементы между first и last, включая элемент, на который указывает first, но не элемент, на который указывает last.
result
Вывести итератор в исходную позицию в последовательности назначения. Это не должно указывать ни на один элемент в диапазоне [first, last).
Подробней про back_inserter
Итератор с обратной вставкой — это особый тип выходного итератора, разработанный для того, чтобы позволить алгоритмам, которые обычно перезаписывают элементы (например, копировать), вместо этого автоматически вставлять новые элементы в конец контейнера. Использование оператора присваивания в возвращаемом итераторе приводит к расширению контейнера на один элемент, который инициализируется присвоенным значением. Возвращенный итератор поддерживает все другие типичные операции выходных итераторов, но не имеет никакого эффекта: все назначенные значения вставляются в конец контейнера.
// Подготовим вектор перед копированием dataVec.reserve(dataVec.size() + dataArraySize); copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
Функция memcpy
// С помощью функции memcpy dataVec.resize(dataVec.size() + dataArraySize); memcpy(&dataVec[dataVec.size() - dataArraySize], &dataArray[0], dataArraySize * sizeof(int));
Подробней про функцию memcpy
void * memcpy ( void * destination, const void * source, size_t num );
Копирует значения num байтов из местоположения, на которое указывает источник, непосредственно в блок памяти, на который указывает место назначения. Базовый тип объектов, на которые указывают указатели источника и назначения, не имеет значения для этой функции; Результатом является двоичная копия данных. Функция не проверяет наличие какого-либо завершающего нулевого символа в источнике — она всегда копирует ровно num байтов. Чтобы избежать переполнений, размер массивов, на которые указывают параметры назначения и источника, должен составлять не менее num байтов.
Описание параметров функции memcy:
destination
Указатель на массив назначения, в который должно быть скопировано содержимое, с приведением типа к указателю типа void
source
Указатель на источник копируемых данных, приведенный к указателю типа const void
Num
Количество байтов для копирования. size_t — целочисленный тип без знака
vector::insert
// С помощью vector::insert dataVec.insert(dataVec.end(), &dataArray[0], &dataArray[dataArraySize]);
Подробней про vector::insert
Вектор расширяется путем вставки новых элементов перед элементом в указанной позиции, эффективно увеличивая размер контейнера на количество вставленных элементов. Это вызывает автоматическое перераспределение выделенного пространства памяти, только если — новый размер вектора превышает текущую емкость вектора. Поскольку векторы используют массив в качестве своего основного хранилища, вставка элементов в позиции, отличные от конца вектора, заставляет контейнер перемещать все элементы, которые были после позиции, в их новые позиции. Как правило, это неэффективная операция по сравнению с операцией, выполняемой для той же операции другими видами контейнеров последовательностей (такими как list или forward_list). Параметры определяют, сколько элементов вставлено и каким значениям они инициализируются
Доступны следующие шаблоны:
iterator insert (const_iterator position, const value_type& val); iterator insert (const_iterator position, size_type n, const value_type& val); template <class InputIterator> iterator insert (const_iterator position, InputIterator first, InputIterator last); iterator insert (const_iterator position, value_type&& val); iterator insert (const_iterator position, initializer_list<value_type> il);
Описание параметров:
position
Положение в векторе, где вставляются новые элементы. iterator — это тип члена, определенный как тип итератора с произвольным доступом, который указывает на элементы
val
Значение, которое будет скопировано (или перемещено) во вставленные элементы. Тип элемента value_type — это тип элементов в контейнере, определенный в deque как псевдоним его первого параметра шаблона (T)
n
Количество элементов для вставки. Каждый элемент инициализируется в копию val. Тип члена size_type является целым типом без знака
first, last
Итераторы, задающие диапазон элементов. Копии элементов в диапазоне [first, last) вставляются в позиции (в том же порядке). Диапазон включает все элементы между первым и последним, включая элемент, на который указывает первый, но не тот, на который указывает последний. Аргумент шаблона функции InputIterator должен быть типом итератора ввода, который указывает на элементы типа, из которого могут быть созданы объекты value_type.
il
Объект initializer_list. Копии этих элементов вставляются по месту (в том же порядке). Эти объекты автоматически создаются из списков объявлений инициализатора. Тип элемента value_type — это тип элементов в контейнере, определенный в векторе как псевдоним его первого параметра шаблона (T)
// Метод 5: vector + vector vector<int> dataVec2(&dataArray[0], &dataArray[dataArraySize]); dataVec.insert(dataVec.end(), dataVec2.begin(), dataVec2.end());
Данный способ самый избыточный
Преобразование QByteArray в вектор
Преобразование из QByteArray в std::vector и QVector и обратно
Объявим значения для преобразования:
using namespace std; QByteArray dataArray = "123456789"; vector<char> dataVec; QVector <char> dataQVec; // С помощью copy для std::vector copy(&dataArray.data()[0], &dataArray.data()[dataArray.size()], back_inserter(dataVec)); // С помощью copy для QVector copy(&dataArray.data()[0], &dataArray.data()[dataArray.size()], back_inserter(dataQVec)); // Memcpy для std::vector dataVec.resize(dataVec.size() + dataArray.size()); memcpy(&dataVec[dataVec.size() - dataArray.size()], &dataArray.data()[0], dataArray.size() * sizeof(char)); // Memcpy для QVector dataQVec.resize(dataQVec.size() + dataArray.size()); memcpy(&dataQVec[dataQVec.size() - dataArray.size()], &dataArray.data()[0], dataArray.size() * sizeof(char)); // С помощью insert для std::vector dataVec.insert(dataVec.begin(), dataArray.begin(), dataArray.end()); // С помощью insert для QVector for (int i = 0; i < dataArray.size(); i++) dataQVec.insert(i,dataArray.at(i));
Преобразование из std::vector и QVector в QByteArray
// // Метод преобразование типа reinterpret_cast для std::vector QByteArray* data = new QByteArray(reinterpret_cast<const char*>(dataVec.data()), dataVec.size()); // Метод преобразование типа reinterpret_cast для QVector QByteArray* data = new QByteArray(reinterpret_cast<const char*>(dataQVec.data()), dataQVec.size());
Подробней про reinterpret_cast
reinterpret_cast преобразует любой тип указателя в любой другой тип указателя, даже из не связанных классов. Результатом операции является простая двоичная копия значения из одного указателя в другой. Разрешены все преобразования указателя: ни указанный контент, ни сам тип указателя не проверяются. Он также может приводить указатели к целочисленным типам или от них.
Формат, в котором это целочисленное значение представляет указатель, зависит от платформы. Единственной гарантией является то, что указатель, приведенный к целочисленному типу, достаточно большому, чтобы полностью его содержать также гарантированно сможет быть приведен обратно к действительному указателю.
Преобразования, которые могут быть выполнены с помощью reinterpret_cast, но не с помощью static_cast, являются операциями низкого уровня, основанными на реинтерпретации двоичных представлений типов, что в большинстве случаев приводит к коду, специфичному для системы,