Перейти к содержимому

Как добавить вектор в вектор c

  • автор:

вствка вектора векторов в вектор векторов

Как вставить вектор векторов в вектор векторов после k -того элемента.То есть если у нас есть вектор векторов 10 на 10, то нужно будет вставить второй вектор векторов 5 на 10 чтобы вышло 15 на 10.

Отслеживать
задан 18 апр 2017 в 19:26
1,059 3 3 золотых знака 14 14 серебряных знаков 29 29 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Нужно использовать метод insert класса std::vector , принимающий диапазон значений, заданных с помощью входных итераторов.

Ниже, в демонстрационной программе показано, как это можно сделать.

#include #include #include int main() < std::vector> v1(10, std::vector( 10, 0 )); std::vector> v2(5, std::vector( 10, 1 )); size_t k = 5; for ( const auto &row : v1 ) < for ( int x : row ) std::cout std::cout << std::endl; v1.insert( std::next( v1.begin(), k ), v2.begin(), v2.end() ); for ( const auto &row : v1 ) < for ( int x : row ) std::cout std::cout

Вывод программы на консоль

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

В общем случае вам надо проверять, что значение переменной k не превышает значения, возвращаемого функцией-членом класса std::vector size . В противном случае в качестве позиции вставки вместо выражения std::next( v1.begin(), k ) вам следует использовать выражение v1.end() .

Введение в вектора в C++

Если до сих пор вы пользовались «чистыми» массивами в языке С++, вы многое потеряли. Под «чистыми» массивами я подразумеваю обычное использование массивов в С++, без специальных функций и методов. Прочитав эту статью, вы узнаете как можно работать с массивами на более высоком уровне, вы сможете обрабатывать массивы (объявление, инициализация, поиск, сортировка и многие другие операции) буквально несколькими строчками.
Итак, что же такое «Вектор» в языке С++? Простыми словами вектор можно описать как абстрактную модель, которая имитирует динамический массив. Пока не стоит углубляться в это определение, сейчас мы приступим к практике и вам все станет понятно.
Если мы хотим использовать векторы в своей программе, необходимо подключить заголовочный файл :

#include

Вектор можно объявить следующим образом:

std::vector myVector; // мы создали пустой вектор типа int myVector.reserve(10); // тут мы зарезервировали память под 10 элементов типа int

Как видно из примера, вектора относятся к пространству имен std . По сути, эти две записи эквивалентны такой записи:

int myVector[10]; // обычное объявление массива

На первый взгляд, объявление вектора оказалось намного более громоздкое. Однако вектора скрывают очень мощный функционал, чего нельзя сказать об обычных массивах С++. Кроме того, вектор можно объявить и в одной строке, вот так:

std::vector myVector(10);

Эта запись эквивалентна двум предыдущим, то есть здесь мы объявили вектор с начальным размером в 10 элементов типа int . Но кроме этого, такой способ объявления вектора не просто выделяет память, но и еще инициализирует все элементы вектора нулями. Вот пример:

#include #include // подключаем модель Векторов using namespace std; int main() < vectormyVector(10); // объявляем вектор размером в 10 элементов и инициализируем их нулями // вывод элементов вектора на экран for(int i = 0; i

Обратите внимание на то, что размер вектора определяется методом size() , это очень удобно, если мы не знаем размер массива. Вывод:

CppStudio.com

0 0 0 0 0 0 0 0 0 0

Если объявить вектор таким образом:

vector myVector; // объявляем пустой вектор myVector.reserve(10); // выделяем память под 10 элементов

то результат работы программы будет другим, в потоке вывода ничего не появится, так как нет начальной инициализации элементов вектора, а значит этот способ объявления вектора выполнится быстрее. Именно в этом и заключается разница этих способов объявления векторов.
Несколькими абзацами выше, я упомянул о начальном размере вектора. Почему же начальный размер? Потому, что, если размера вектора будет не хватать, вектор автоматически будет увеличиваться, при добавлении новых элементов, пересчитывая свой размер. Это очень удобно, так как за частую мы не можем предугадать размер массива, который нам нужен для работы программы. Более подробно мы рассмотрим этот пример немного позже.
Смотрите как легко можно скопировать вектор:

#include #include // подключаем модель Векторов using namespace std; int main() < vectormyVector1(10); // вывод элементов вектора на экран cout cout << "\nСкопированный массив: "; vectormyVector2(myVector1); // при объявлении второго вектора, копируется - первый for(int i = 0; i < myVector2.size(); i++) < myVector2[i] = i; cout return 0; >

CppStudio.com

Входной массив: 0 1 2 3 4 5 6 7 8 9 Скопированный массив: 0 1 2 3 4 5 6 7 8 9

Из результат работы программы хорошо видно ,что в строке 14, была создана копия вектора myVector1 . Рассмотрим программу, в которой сравниваются два массива:

#include #include using namespace std; int main() < vectorarray1(3); // инициализируем элементы вектора array1 array1[0] = 4; array1[1] = 2; array1[2] = 1; vector array2(3); // инициализируем элементы вектора array2 array2[0] = 4; array2[1] = 2; array2[2] = 1; // сравниваем массивы if (array1 == array2) < cout return 0; >

CppStudio.com

array1 == array2

Итак, массивы мы инициализировали обыкновенным для нас способом, строки 8-10 и 13-15. Самое удивительное то, что операция сравнивания векторов выполняется в одну строку, строка 17. Попробуйте сделать то же самое с обычными массивами в С++, уверен, что у вас ничего не получится.
До этого, во всех примерах в этой статье я выводил элементы массива используя цикл, с векторами можно обойтись и без него. Смотрим как именно это делается.

#include #include #include // заголовочный файл итераторов using namespace std; int main() < vectorarray1; // создаем пустой вектор // добавляем в конец вектора array1 элементы 4, 3, 1 array1.insert(array1.end(), 4); array1.insert(array1.end(), 3); array1.insert(array1.end(), 1); // вывод на экран элементов вектора copy( array1.begin(), // итератор начала массива array1.end(), // итератор конца массива ostream_iterator(cout," ") //итератор потока вывода ); return 0; >

CppStudio.com

4 3 1

Итак, начнем по порядку. В строке 3 я добавил новый заголовочный файл, для использования итераторов. Так как в строке 8 мы создали пустой вектор, то конец вектора — это его начало, ведь в векторе нет никаких элементов. Так что, когда мы добавляем новые элементы в массив, мы должны использовать итератор array1.end() , а не итератор array1.begin() . Иначе порядок элементов в массиве станет противоположным. В строках 10-12 мы используем метод insert(), который позволяет вставить элемент в массив. Ну и самое главное, вывод элементов массива выполняется не через цикл а через операцию copy() . В первых двух параметрах мы указали итераторы начала и конца вектора. В третьем параметре указан поток вывода cout — ostream_iterator(cout," ") . Как по мне, такой способ организации вывода на экран намного красивее выглядит, хотя, возможно сразу и не понятен для новичка. Но вы просто постарайтесь его принять как должное и запомнить.

Урок №95. std::vector (векторы)

На предыдущем уроке мы рассматривали std::array, который является более безопасной и удобной формой обычных фиксированных массивов в языке C++. Аналогично, в Стандартной библиотеке C++ есть и улучшенная версия динамических массивов (более безопасная и удобная) — std::vector.

В отличие от std::array, который недалеко отходит от базового функционала обычных фиксированных массивов, std::vector идет в комплекте с дополнительными возможностями, которые делают его одним из самых полезных и универсальных инструментов в языке C++.

Оглавление:

Векторы

Представленный в C++03, std::vector (или просто «вектор») — это тот же динамический массив, но который может сам управлять выделенной себе памятью. Это означает, что вы можете создавать массивы, длина которых задается во время выполнения, без использования операторов new и delete (явного указания выделения и освобождения памяти). std::vector находится в заголовочном файле vector. Объявление std::vector следующее:

// Нет необходимости указывать длину при инициализации
std :: vector < int >array ;
std :: vector < int >array2 = < 10 , 8 , 6 , 4 , 2 , 1 >; // используется список инициализаторов для инициализации массива

std :: vector < int >array3 < 10 , 8 , 6 , 4 , 2 , 1 >; // используется uniform-инициализация для инициализации массива (начиная с C++11)

Обратите внимание, что в неинициализированном, что в инициализированном случаях вам не нужно явно указывать длину массивов. Это связано с тем, что std::vector динамически выделяет память для своего содержимого по запросу.

Подобно std::array, доступ к элементам массива может выполняться как через оператор [] (который не выполняет проверку диапазона), так и через функцию at() (которая выполняет проверку диапазона):

array [ 7 ] = 3 ; // без проверки диапазона
array . at ( 8 ) = 4 ; // с проверкой диапазона

В любом случае, если вы будете запрашивать элемент, который находится вне диапазона array , длина вектора автоматически изменяться не будет. Начиная с C++11, вы также можете присваивать значения для std::vector, используя список инициализаторов:

array = < 0 , 2 , 4 , 5 , 7 >; // ок, длина array теперь 5
array = < 11 , 9 , 5 >; // ок, длина array теперь 3

В таком случае вектор будет самостоятельно изменять свою длину, чтобы соответствовать количеству предоставленных элементов.

Нет утечкам памяти!

Когда переменная-вектор выходит из области видимости, то она автоматически освобождает память, которую контролировала (занимала). Это не только удобно (так как вам не нужно это делать вручную), но также помогает предотвратить утечки памяти. Рассмотрим следующий фрагмент:

void doSomething ( bool value )
int * array = new int [ 7 ] < 12 , 10 , 8 , 6 , 4 , 2 , 1 >;
// Делаем что-нибудь
delete [ ] array ; // если value == true, то этот стейтмент никогда не выполнится

Если переменной value присвоить значение true , то array никогда не будет удален, память никогда не будет освобождена и произойдет утечка памяти.

Однако, если бы array был вектором, то подобное никогда бы и не произошло, так как память освобождалась бы автоматически при выходе array из области видимости (независимо от того, выйдет ли функция раньше из области видимости или нет). Именно из-за этого использование std::vector является более безопасным, чем динамическое выделение памяти через оператор new.

Длина векторов

В отличие от стандартных динамических массивов, которые не знают свою длину, std::vector свою длину запоминает. Чтобы её узнать, нужно использовать функцию size():

std :: vector < int >array < 12 , 10 , 8 , 6 , 4 , 2 , 1 >;
std :: cout << "The length is: " << array . size ( ) << '\n' ;

The length is: 7

Изменить длину стандартного динамически выделенного массива довольно проблематично и сложно. Изменить длину std::vector так же просто, как вызвать функцию resize():

std :: vector < int >array < 0 , 1 , 2 >;
array . resize ( 7 ) ; // изменяем длину array на 7
std :: cout << "The length is: " << array . size ( ) << '\n' ; for ( auto const & element : array ) std :: cout << element << ' ' ;

The length is: 7
0 1 2 0 0 0 0

Здесь есть две вещи, на которые следует обратить внимание. Во-первых, когда мы изменили длину array , существующие значения элементов сохранились! Во-вторых, новые элементы были инициализированы значением по умолчанию в соответствие с определенным типом данных (значением 0 для типа int).

Длину вектора также можно изменить и в обратную сторону (обрезать):

std :: vector < int >array < 0 , 1 , 4 , 7 , 9 , 11 >;
array . resize ( 4 ) ; // изменяем длину array на 4
std :: cout << "The length is: " << array . size ( ) << '\n' ; for ( auto const & element : array ) std :: cout << element << ' ' ;

The length is: 4
0 1 4 7

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

Заключение

Это вводная статья, предназначенная для ознакомления с основами std::vector. На следующих уроках мы детально рассмотрим std::vector, в том числе и разницу между длиной и ёмкостью вектора, и то, как в std::vector выполняется выделение памяти.

Поскольку переменные типа std::vector могут сами управлять выделенной себе памятью (что помогает предотвратить утечку памяти), отслеживают свою длину и легко её изменяют, то рекомендуется использовать std::vector вместо стандартных динамических массивов.

(478 оценок, среднее: 4,88 из 5)

Урок №94. Введение в std::array

Глава №6. Итоговый тест

Комментариев: 21

Есть ли разница в позиции ключевого слова const в объявлении цикла foreach или оба варианта эквивалентны и обозначают константную ссылку на текущий элемент массива?

for ( auto const & element : array )
std :: cout << element << ' ' ; for ( const auto & element : array ) std :: cout << element << ' ' ;

Когда мы пытаемся работать с элементом массива вне диапазона то происходит ошибка времени выполнения, правильно? Ибо с этой ошибкой проект собирается(VS2019).

Поскольку ошибка возникает во время работы кода, а не на этапе компиляции, то это ошибка времени выполнение. При желании можно проверить это, запустив этот код:

std :: vector < int >array ;
array . resize ( 3 ) ;
system ( "pause" ) ;
std :: cout << array . at ( 4 ) ;

В данном случае код компилируется и начинает работу, и после объявления вектора выполнение кода ставиться на паузу

Я не очень поняла один момент, может, кто-то сможет подсказать, буду признательна)
В начале урока написано: "Начиная с C++11, вы также можете присваивать значения для std::vector, используя список инициализаторов … В таком случае вектор будет самостоятельно изменять свою длину, чтобы соответствовать количеству предоставленных элементов."
А в конце показывают функцию resize( ), которая делает то же самое, но при этом является затратной.
Так вооот, насколько затратным будет изменить длину вектора через список инициализаторов и зачем тогда нужна отдельная функция? Только для работы с крупными объемами данных, чтобы не переписывать их все вручную? Или есть ещё что-то?

Jaroshevskii :

Мне кажется что изменять длину std::vector что через метод resize(), что через список инициализаторов будет одинаково затратным (возможно в будущих уроках это будет более подробно описано). Отличие же resize() от списка инициализаторов в том что при вызове метода resize() он изменяет длину std::vector и при этом те элементы которые входят в диапазон размера будет сохранены без изменений.
Изменения размера с помощью списка инициализаторов изменит не только длину std::vector но и запишит вместо старых элементов новые (те которые были записаны в списке инициализаторов).

Юрий, вы восхитительны! У вас не только классные уроки, но и абсолютно замечательная система кросс-навигации между ними — на сайт изначально попала в поисках информации про классы. Пойду читать ваши уроки с самого начала, у меня хоть какая-то минимальная база знаний и есть, но всё равно так много новых и полезных штук открываю ��

Юрий :

Доброго времени суток!
В этой статье нет ни слова про дву-х, трё-х, *N — мерные векторы и массивы пространства имён std. Подозреваю что можно реализовать аналогично указателю на указатель (древовидная структура) массив в массиве, но надеюсь есть способ проще и удобней. Конечно сам доберусь до этого, но надеюсь получить ответ и возможно мой вопрос поможет улучшить/дополнить 95-й урок.

Это было вводное занятие, поверхностное обозрение темы, написано же в конце. Дальше, естественно, будет подробнее

Добавить вектор в вектор с максимальной производительностью

Я создаю вектор в отдельном потоке, после этого мне его надо сохранить вызвав функцию Data::insert(). После сохранения изначальный вектор мне больше не нужен. Как лучше всего это сделать? Заранее спасибо.

template class Data < public: Data(); void insert(vector& d) < if (d.empty()) throw range_error("Data::insert(): Vector is empty!"); lock_guardl(data_mutex_); // Add d to the vector data_ > private: vector data_; mutex data_mutex_; >; 

ECLIPSE ★
26.12.18 11:48:16 MSK

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *