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

Как обнулить вектор c

  • автор:

Как обнулить вектор c

Для добавления элементов в вектор применяется функция push_back() , в которую передается добавляемый элемент:

#include #include int main() < std::vectornumbers; // пустой вектор numbers.push_back(5); numbers.push_back(3); numbers.push_back(10); for(int n : numbers) cout << n << "\t"; // 5 3 10 std::cout

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

Функция emplace_back() выполняет аналогичную задачу — добавляет элемент в конец контейнера:

std::vector numbers< 1, 2, 3, 4, 5 >; numbers.emplace_back(8); // numbers = < 1, 2, 3, 4, 5, 8 >;

Добавление элементов на определенную позицию

Ряд функций позволяет добавлять элементы на определенную позицию.

  • emplace(pos, value) : вставляет элемент value на позицию, на которую указывает итератор pos
  • insert(pos, value) : вставляет элемент value на позицию, на которую указывает итератор pos, аналогично функции emplace
  • insert(pos, n, value) : вставляет n элементов value начиная с позиции, на которую указывает итератор pos
  • insert(pos, begin, end) : вставляет начиная с позиции, на которую указывает итератор pos, элементы из другого контейнера из диапазона между итераторами begin и end
  • insert(pos, values) : вставляет список значений начиная с позиции, на которую указывает итератор pos
std::vector numbers< 1, 2, 3, 4, 5 >; auto iter = numbers.cbegin(); // константный итератор указывает на первый элемент numbers.emplace(iter + 2, 8); // добавляем после второго элемента numbers = < 1, 2, 8, 3, 4, 5>;
std::vector numbers1< 1, 2, 3, 4, 5 >; auto iter1 = numbers1.cbegin(); // константный итератор указывает на первый элемент numbers1.insert(iter1 + 2, 8); // добавляем после второго элемента //numbers1 = < 1, 2, 8, 3, 4, 5>; std::vector numbers2 < 1, 2, 3, 4, 5 >; auto iter2 = numbers2.cbegin(); // константный итератор указывает на первый элемент numbers2.insert(iter2 + 1, 3, 4); // добавляем после первого элемента три четверки //numbers2 = < 1, 4, 4, 4, 2, 3, 4, 5>; std::vector values < 10, 20, 30, 40, 50 >; std::vector numbers3 < 1, 2, 3, 4, 5 >; auto iter3 = numbers3.cbegin(); // константный итератор указывает на первый элемент // добавляем после первого элемента три первых элемента из вектора values numbers3.insert(iter3 + 1, values.begin(), values.begin() + 3); //numbers3 = < 1, 10, 20, 30, 2, 3, 4, 5>; std::vector numbers4 < 1, 2, 3, 4, 5 >; auto iter4 = numbers4.cend(); // константный итератор указывает на позицию за последним элементом // добавляем в конец вектора numbers4 элементы из списка < 21, 22, 23 >numbers4.insert(iter4, < 21, 22, 23 >); //numbers4 = < 1, 2, 3, 4, 5, 21, 22, 23>;

Удаление элементов

Если необходимо удалить все элементы вектора, то можно использовать функцию clear :

std::vector v < 1,2,3,4 >; v.clear();

Функция pop_back() удаляет последний элемент вектора:

std::vector v < 1,2,3,4 >; v.pop_back(); // v =

Если нужно удалить элемент из середины или начала контейнера, применяется функция std::erase() , которая имеет следующие формы:

  • erase(p) : удаляет элемент, на который указывает итератор p. Возвращает итератор на элемент, следующий после удаленного, или на конец контейнера, если удален последний элемент
  • erase(begin, end) : удаляет элементы из диапазона, на начало и конец которого указывают итераторы begin и end. Возвращает итератор на элемент, следующий после последнего удаленного, или на конец контейнера, если удален последний элемент

std::vector numbers1 < 1, 2, 3, 4, 5, 6 >; auto iter = numbers1.cbegin(); // указатель на первый элемент numbers1.erase(iter + 2); // удаляем третий элемент // numbers1 = < 1, 2, 4, 5, 6 >std::vector numbers2 = < 1, 2, 3, 4, 5, 6 >; auto begin = numbers2.cbegin(); // указатель на первый элемент auto end = numbers2.cend(); // указатель на последний элемент numbers2.erase(begin + 2, end — 1); // удаляем с третьего элемента до последнего // numbers2 =

Также начиная со стандарта С++20 в язык была добавлена функция std::erase() . Она не является частью типа vector. В качестве первого параметра она принимает вектор, а в качестве второго — элемент, который надо удалить:

std::vector numbers3 < 1, 2, 3, 1, 5, 6 >; std::erase(numbers3, 1); // numbers3 =

В данном случае удаляем из вектора numbers3 все вхождения числа 1.

Размер вектора

С помощью функции size() можно узнать размер вектора, а с помощью функции empty() проверить, путой ли вектор:

#include #include int main() < std::vectornumbers; if(numbers.empty()) std::cout

С помощью функции resize() можно изменить размер вектора. Эта функция имеет две формы:

  • resize(n) : оставляет в векторе n первых элементов. Если вектор содержит больше элементов, то его размер усекается до n элементов. Если размер вектора меньше n, то добавляются недостающие элементы и инициализируются значением по умолчанию
  • resize(n, value) : также оставляет в векторе n первых элементов. Если размер вектора меньше n, то добавляются недостающие элементы со значением value

std::vector numbers1 < 1, 2, 3, 4, 5, 6 >; numbers1.resize(4); // оставляем первые четыре элемента — numbers1 = numbers1.resize(6, 8); // numbers1 =

Важно учитывать, что применение функции resize может сделать некорректными все итераторы, указатели и ссылки на элементы.

Изменение элементов вектора

Функция assign() позволяет заменить все элементы вектора определенным набором:

std::vector langs = < "Java", "JavaScript", "C">; langs.assign(4, «C++»); // langs =

В данном случае элементы вектора заменяются набором из четырех строк «C++».

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

std::vector langs< "Java", "JavaScript", "C">; langs.assign(< "C++", "C#", "C">); // langs =

Еще одна функция — swap() обменивает значения двух контейнеров:

std::vector clangs < "C++", "C#", "Java" >; std::vector ilangs < "JavaScript", "Python", "PHP">; clangs.swap(ilangs); // clangs = < "JavaScript", "Python", "PHP">; for(std::string lang : clangs)

Сравнение векторов

Векторы можно сравнивать — они поддерживают все операции сравнения: , =, ==, !=. Сравнение контейнеров осуществляется на основании сравнения пар элементов на тех же позициях. Векторы равны, если они содержат одинаковые элементы на тех же позициях. Иначе они не равны:

std::vector v1 ; std::vector v2 ; std::vector v3 ; bool v1v2 = v1 == v2; // true bool v1v3 = v1 != v3; // true bool v2v3 = v2 == v3; // false

C++: Очистка std::vector

Уважаемые программисты! Допустим, создается и заполняется vector:

vector float> items; . float *x; for( int i = 0; i100; i++) < x = new float; *x = 1.0f; items.push_back( *x); >;

При этом создаваться могут экземпляры struct и классов, поэтому в вектор записываются ссылки.

Если необходимо очистить динамическую память, достаточно

items.clear( );
float *x; if ( items.size( ) > 0)< for( int i = 0; iitems.size( ); i++) < *x = items[i]; SAFE_DELETE( x); >; >; items.clear( );

(второй вариант более логичен, но возникает run-time ошибка)?

  • return []()<>;
  • Участник

#1
10:46, 25 сен 2014

Странствуй 8 летучи с++, ты пихаешь объекты в вектор по значению, память утекает.

  • Walter Sullivan
  • Постоялец

#2
10:47, 25 сен 2014

Здесь всё плохо.
У вас утечка памяти.

items.clear() просто удаляет все элементы вектора, не освобождает никакую память.

  • Kartonagnick
  • Постоялец

#3
10:58, 25 сен 2014

float *x; // for( int i = 0; i100; i++) < x = new float; // *x = 1.0f; items.push_back( *x); >;

Предыдущий адрес теряется. Память по нему уже не освободить. Утечка.

#4
11:02, 25 сен 2014

vector float*> items; . float *x; for( int i = 0; i100; i++) < x = new float; *x = 1.0f; items.push_back( x); > if ( items.size( ) > 0) < for( int i = 0; i  items.size( ); i++) < *x = items[i]; SAFE_DELETE( x); > > items.clear( );

float’ы конечно не разумно хранить таким образом, но ошибку свою надеюсь ты поймешь. 🙂

#5
11:17, 25 сен 2014

Изображение

old_proger
facepalm

  • Kartonagnick
  • Постоялец

#6
11:23, 25 сен 2014

old_proger
Вообще, ваш код можно переписать без потери смысла вот так:

vector float> items; . for( int i = 0; i100; i++) items.emplae_back( 1.0f); // // нужное вам значение сразу же запихивайте в вектор // рекомендую использовать emplace_back вместо push_back //для тяжелых объектов это работает быстрее поскольку позволяет избежать копирования . items.clear( ); // // так же, если закончится время жизни вектора, он самостоятельно позаботится об очистке памяти за собой

Суть использования высокоуровневых механизмов таких, как контейнеры, смарт-поинтеры и прочее — в том и заключается,
что вам больше не нужно вручную выделять память, и самостоятельно следить за ней.

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

#7
11:29, 25 сен 2014

old_proger
> При этом создаваться могут экземпляры struct и классов, поэтому в вектор
> записываются ссылки.

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

#8
11:53, 25 сен 2014

0iStalker
> В вектор запихивай или значения или смартпоинтеры. а за ручное выделение
> памяти в С++, без важной на то причины, надо руки отрывать.
Какие смарт поинтеры? За использование shared_ptr без уважительной причины, нужно не то что руки отрывать, от компа отлучать на не определенное время.

Как обнулить вектор c

Вектор — одномерный массив проиндексированных элементов. Вектор представляет собой пример наиболее полного стандартного контейнера. Для использования вектора стандартной библиотеки необходимо подключить файл с описанием вектора. При объявлении вектора (так же и других контейнеров) в треугольных скобках указывается тип данных элементов, хранящихся в векторе. Доступ к элементам вектора можно осуществлять через квадратные скобки, так же как и для обычных массивов.

Доступ к функциям вектора производится через оператор «.». Вектор – это особый тип данных, шаблон класса. Подробнее о классах и шаблонах см. главу 4 и раздел 5.4.

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

#include using namespace std; vectordouble> x; // создание вектора x.resize(10); // изменение размера вектора x.resize(x.size()+100); // изменение размера вектора double sum=0.0; for(int i=0; i//доступ по индексу >

Полный список функций вектора см. Приложение 5.

Рассмотрим более подробно пример работы с вектором. Обратите внимание, что в этом примере вектор передается в функцию по ссылке, т.к. классы и массивы большого объема нерационально копировать каждый раз при вызове функции, что происходит при передачи по значению. Если функция не должна изменить содержимое контейнера, дополнительно указывается ключевое слово const.

///////////////////////////////////////////////////////////////////////////// // Прикладное программирование // Пример 3.3. Пример работы с контейнером vector // // Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru // Университет ИТМО ///////////////////////////////////////////////////////////////////////////// #include // подключение библиотеки ввода-вывода #include // подключение описания вектора #include // для работы с таймером using namespace std; // подключение стандартного пространства имен для использования библиотек // прототипы функций int min(const vectordouble>& data); void fill_rand(vectordouble>& data, double max, double min); ///////////////////////////////////////////////////////////////////////////// // пример передачи вектора в функцию // функция находит индекс минимального числа в векторе int min(const vectordouble>& data) < int index=0; double min=data[0]; for(int i=1; iif(data[i] > return index; > ///////////////////////////////////////////////////////////////////////////// // Функция заполнения вектора случайными числами // data - вектор для заполнения // max - максимальное число случайного диапазона // min - минимальное число случайного диапазона void fill_rand(vectordouble>& data, double max, double min) < // устанавливает стартовую точку для генерации // случайных чисел по текущему времени srand((unsigned) clock()); for(int i=0; i > ///////////////////////////////////////////////////////////////////////////// void main() < vectordouble> x; // создание вектора // ввод количества элементов в векторе int n; cout"input vector size: "; cin>>n; // 1. заполнение контейнера индексами // заполнение контейнера for(int i=0; i// добавить элемент в конец контейнера x.push_back(i); > // вывод всех элементов контейнера cout<for(int i=0; i; //доступ по индексу > // 2. заполнение контейнера случайными числами от 1 до 100 // очистить контейнер x.clear(); // изменить размер x.resize(20); // заполнить случайными числами fill_rand(x, 1, 100); // вывод всех элементов контейнера cout<for(int i=0; i//доступ по индексу > // вывод минимального числа в контейнере cout<// x[min(x)] аналогично записи int i=min(x); x[i]; > /////////////////////////////////////////////////////////////////////////////// 

При работе с вектором мы сталкиваемся с такими понятиями как размер и емкость. Размер — количество элементов, хранимых в контейнере, можно узнать с помощью функции size(), а изменить с помощью resize(). Операции push_back(), insert(), erase() также изменяют размеры вектора. Когда размеры вектора изменяются, то все его элементы могут быть перемещены в новую область памяти, поэтому хранить указатели на элементы вектора не имеет смысла и может быть опасно. Всегда нужно работать через итераторы (см.раздел 3.5).

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

bool res=x.empty(); // эквивалентно x.size() == 0 

При работе с вектором можно выделить (зарезервировать) некоторую область памяти для потенциального расширения. Использование функции reserve() обеспечить выделение памяти для новых элементов контейнера. При этом вставка новых элементов или изменение размеров с помощью resize() не потребует перераспределения хранимого вектора в памяти. Определить «емкость» вектора можно с помощью функции capaсity().

Операции с векторами в STL

Размер вектора можно узнать при помощи универсального метода size() , возвращающего для всех контейнеров в STL их размер. Также есть метод empty() , возвращающий логическое значение ( true , если вектор пустой).

Размер вектора можно изменить в любой момент, при помощи метода resize . У этого метода может быть один или два параметра. Вызов метода resize(n) изменяет размер вектора до n элементов (длина вектора может как уменьшится, так и увеличиться). Вызов метода resize(n, val) изменяет размер вектора до n элементов, и если при этом размер вектора увеличивается, то новые элементы получают значение, равное val.

Очень часто бывает полезно добавлять элементы в конец вектора по одному и удалять элементы из конца вектора по одному. Для добавления нового элемента, равного val в конец вектора используется метод push_back(val) . Для удаления последнего элемента вектора используется метод pop_back() — он не возвращает значения.

Добавление элемента в конец вектора осуществляется в среднем за O(1). Это реализовано за счет того, что память для хранения элементов вектора выделяется “с запасом”, то есть можно будет добавлять элементы по одному, пока не кончится запас памяти. Если запас памяти исчерпан, выделяется новая память, при этом «запас» размера вектора удваивается.

Очистить вектор можно при помощи метода clear() .

Вставка и удаление элементов в середину вектора

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

Итератор — специальный объект, указывающий на элемент вектора (или другой структуры данных). Итератор на элемент с индексом i можно получить при помощи выражения a.begin() + i . Кроме того, можно при помощи итератора a.end() “отсчитывать” элементы, начиная с конца. При этом a.end() будет итератором на элемент, следующий за последним, a.end() будет итератором на последний элемент, то есть то же самое, что a.begin() + a.size() — 1 , a.end() — 2 — второй элемент с конца и т.д.

Удаление элементов: метод erase

Метод erase позволяет удалять из середины вектора один или несколько элементов. Если вызвать метод erase с одним параметром–итератором, то будет удален соответствующий элемент из вектора, то есть для удаления элемента с индексом i из вектора a нужно вызвать метод следующим образом:

a.erase(a.begin() + i);

Методу erase передать два итератора на начало и конец удаляемого фрагмента, например:

a.erase(a.begin() + i, a.begin() + j);

В этом случае будут удалены элементы с индексами от i (включительно) до j не включительно, то есть элементы a[i] , a[i + 1] , . a[j — 1] . Всего будет удалено j — i элементов.

Методу erase можно передавать и итераторы, полученные относительно итератора end . Например, удалить из вектора три последних элемента можно так:

a.erase(a.end() - 3, a.end());

Подробней про его использование можно прочитать в документации.

Вставка элементов: метод insert

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

Примеры использования метода insert :

Вставка одного элемента со значением val в позицию с индексом i :

a.insert(a.begin() + i, val);

Вставка нескольких равных (количеством count ) элементов со значением val в позицию с индексом i :

a.insert(a.begin() + i, count, val);

Вставка в вектор a в позицию с индексом i фрагмент вектора b с индексами от start включительно до finish не включительно:

a.insert(a.begin() + i, b.begin() + start, b.begin() + finish);

В качестве параметром могут использоваться произвольные итераторы. Рассмотрим несколько примеров:

Весь вектор b добавить в конец вектора a :

a.insert(a.end(), b.begin(), b.end());

Последние 5 элементов вектора b вставить в начало вектора a :

a.insert(a.begin(), b.end() - 5, b.end());

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

Присваивание и сравнение векторов

Содержимое одного вектора можно целиком скопировать в другой вектор при помощи операции присваивания. При этом размер вектора A автоматически изменится и будет равен размеру вектора B . A = B .

Также векторы можно сравнивать на равенство и неравенство ( A == B , A != B ), и сравнивать их содержимое в лексикографическом порядке ( A < B , A B , A >= B ).

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

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