Вектора в С++ часть 5 (функции insert(), swap(), shrink_to_fit())

Вектора, позволяют помещать число в любую ячейку вектора (даже если эта ячейка уже занята), пример для понимания:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
   vector <int> vecInt(3,100); ///Создаем вектор из 3 элементов и заполняем его значением 100
   vector <int>::iterator it;
   it = vecInt.begin(); ///Итератор указывает на vec[0]

   ///Вектор расширяется теперь до 4 элементов
   vecInt.insert (it,200); ///И первым элементом записывается 200

   ///Вектор расширяется теперь до 5 элементов
   it = vecInt.begin() + 3;///Вектор указывает на 4 элемент (0-элемент+3-элемента)
   vecInt.insert(it,300);///И четвертым элементом записывается 300
   vecInt.insert(it+1,900);///Вектор расширяется теперь до 6 элементов и 5 элементом записывается 900

   cout << "Vector contains: ";
   for (int i=0; i<vecInt.size(); ++i)
   {
      cout << vecInt[i] << ends;
   }

   cout << "\nVector max_size: " << vecInt.max_size();
   cout << "\nVector size: " << vecInt.size(); ///Выводим размер вектора
   vecInt.resize(10); ///Увеличиваем размер до 10 элементов
   cout << "\nNew vector size: " << vecInt.size() << endl; ///Выводим размер вектора
   return 0;
}

Работа нашей программы:

CppStudio.com
Vector contains: 200 100 100 300 900 100
Vector max_size: 1073741823
Vector size: 6 New vector size: 10

В 6 строке объявлен вектор размером из трех элементов типа int  и сразу же заполнили его числом 100. В строке 7 мы объявляем итератор it, в 8 строке наш итератор указывает на нулевой элемент нашего вектора. В 11 строке  мы встречаем новую функцию vector::insert().

Функция vector::insert() принимает два аргумента (первый – указатель на ячейку вектора, куда будет помещено число, второй – само помещаемое число). Так как итератор it указывает на vecInt[0], нулевой элемент вектора, то теперь vecInt[0]=200. Длина вектора соответственно увеличивается на один элемент. В строке 14 итератор it теперь указывает на третий элемент вектора, т. е. vecInt[3], соответственно назначение строки 15 становиться уже понятно.

В строке 16 число 900 мы записываем в позицию it+1 или vecInt[3+1]. В строках с 19-22 осуществляется вывод вектора, но это должно быть уже Вам понятно. В строке 24 используется функция vector::max_size(), которая выводит максимальный размер вектора, т. е. максимально возможное количество, элементов которое может вместить в себя вектор. В строке 26 встречается новая функция vector::resize (), функция позволяет увеличить размер вектора до заданной величины, в данном случае вектор расширяется до 10 элементов.

Если функция vector::resize() позволяет уменьшить размер вектора, то функция vector::reserve() имеет обратное действие, она позволяет расширить вектор до заданной величины, рассмотрим пример:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
  vector <int> vecFirst ,vecSecond; /// Создаем два вектора
  for ( int i=0; i<10; ++i)
  {
      vecFirst.push_back(i); /// заполняем первый вектор
      vecSecond.push_back(i*10); /// заполняем второй вектор
  }

  cout << "vecFirst contains: ";
  for (int i=0; i<vecFirst.size(); ++i)
  cout << vecFirst[i] << ends;

  cout << "\nvecSecond contains: ";
  for (int i=0; i<vecSecond.size(); ++i)
  cout << vecSecond[i] << ends;

  vecFirst.swap(vecSecond); ///меняем местами элементы векторов

  cout << "\nvecFirst contains: ";
  for (int i=0; i<vecFirst.size(); ++i)
  cout << vecFirst[i] << ends;

  cout << "\nvecSecond contains: ";
  for (int i=0; i<vecSecond.size(); ++i)
  cout << vecSecond[i] << ends;

  swap (vecFirst.back(),vecSecond.back()); ///поменяли местами последний элемент в обоих векторах

  cout << "\nvecFirst contains: ";
  for (int i=0; i<vecFirst.size(); ++i)
  cout << vecFirst[i] << ends;

  cout << "\nvecSecond contains: ";
  for (int i=0; i<vecSecond.size(); ++i)
  cout << vecSecond[i] << ends;

  ///вместимость вектора до увеличения его размера
  cout << "\nvecFirst capacity before reserve: " << vecFirst.capacity();
  vecFirst.reserve(20);

  ///вместимость вектора после увеличения его размера
  cout << "\nvecFirst capacity after reserve: " << vecFirst.capacity();
  return 0;
}

Работа нашей программы:

CppStudio.com
vecFirst contains: 0 1 2 3 4 5 6 7 8 9
vecSecond contains: 0 10 20 30 40 50 60 70 80 90
vecFirst contains: 0 10 20 30 40 50 60 70 80 90
vecSecond contains: 0 1 2 3 4 5 6 7 8 9
vecFirst contains: 0 10 20 30 40 50 60 70 80 9
vecSecond contains: 0 1 2 3 4 5 6 7 8 90
vecFirst capacity before reserve: 16
vecFirst capacity after reserve: 20

В строке 7 мы объявили два вектора. С помощью цикла в строках 8-12 заполняем наши вектора. В строках 16 и 20, выводим содержимое наших векторов. В строке 22 нам встречается функция vector::swap(), которая позволяет поменять содержимое наших векторов. Иными слова содержимое вектора vecFirst теперь принадлежит vecSecond, а содержимое vecSecond принадлежит  vecFirst. Строки 26 и 30 (где осуществляется вывод на экран) наглядно демонстрируют это.

В строке 32, я хотел продемонстрировать, что можно менять местами только определенные элементы векторов. В этой строке у вектора vecFirst и вектора vecSecond происходит обмен последними элементами (если вдруг забыли: функция vector::back() обращается к последнему элементу вектора). В 36, 40 строках   выводятся на экран наши вектора. В строке 43 производится вывод вместимости вектора. В строке 44 при помощи функции vector::reserve() мы просим увеличить этот объем до 20 элементов и в строке 47 мы действительно видим, что так и вышло.

У векторов есть замечательная функция vector::shrink_to_fit() позволяющая уменьшить количество используемой памяти вектором, пример:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
  vector <int> vecFirst (10); 

  ///кол-во элементов, которое может содержать наш вектор
  cout << "Capacity of vecFirst before clear: " << vecFirst.capacity();
  vecFirst.clear();

  ///кол-во элементов, которое может содержать наш вектор после удаления всех элементов
  cout << "\nCapacity of vecFirst after clear: " << vecFirst.capacity();
  vecFirst.shrink_to_fit();

  ///очищение памяти
  cout << "\nCapacity of vecFirst after shrink_to_fit: " << vecFirst.capacity();

  return 0;
}

Работа программы:

CppStudio.com
Capacity of vecFirst before clear: 10
Capacity of vecFirst after clear: 10
Capacity of vecFirst after shrink_to_fit: 0

ВАЖНО Функцию vector:: shrink_to_fit() я вынес в отдельную программу, потому, как она введена в стандарте C++11 и если Ваш компилятор не поддерживает этот стандарт, код не скомпилируется.

В строке 7 объявили вектор, состоящий из десяти элементов. В 10 строке мы снова встречаем функцию vector::capacity() .Как видите вектор содержит 10 элементов. В 11 строке мы очищаем этот вектор (удаляем в нем все элементы). В 14 строке мы видим, что наш вектор может содержать 10 элементов (не забываем, что вектор уже пуст). В 15 строке мы знакомимся с функцией vector:: shrink_to_fit(). Эта функция уменьшает количество используемой памяти нашего вектора (иначе говоря, у нас есть вектор из 10 элементов, но он пустой, эта функция возвращает память системе, которую занимал наш пустой вектор). В 18 строке мы видим, что вектор сжался в нуль.

Автор: Marienko L.
Дата: 07.02.2014
Поделиться:

Комментарии

  1. Max Shvayuk

    Max Shvayuk

    В строке 14 итератор it теперь указывает на третий элемент вектора, т. е. vecInt[3], соответственно назначение строки 15 становиться уже понятно.

     it = vecInt.begin() + 3;///Вектор указывает на 4 элемент (0-элемент+3-элемента)

    Исправьте в тексте, vecInt[3] — это не третий, а четвертый элемент массива. (0, 1, 2, 3)

     

  2. k4154r

    В строке 26 встречается новая функция vector::resize (), функция позволяет увеличить размер вектора до заданной величины, в данном случае вектор расширяется до 10 элементов.

    //

    Если функция vector::resize() позволяет уменьшить размер вектора, то функция vector::reserve() имеет обратное действие, она позволяет расширить вектор до заданной величины

    vector::resize();

    Расширяет или уменьшает размер?

  3. Melkom

    it = vecInt.begin() + 3;///Вектор указывает на 4 элемент (0-элемент+3-элемента)
       vecInt.insert(it,300);///И четвертым элементом записывается 300
       vecInt.insert(it+1,900);///Вектор расширяется теперь до 6 элементов и 5 элементом записывается 900

    По каким-то причинам после использования первого insert’a итератор сбрасывается, приходится делать:

    it = vecInt.begin() + 3;
       vecInt.insert(it,300); // После этой строчки it становится -17891602
    it = vecInt.begin() + 3; // Приходится заново инициализировать it
       vecInt.insert(it+1,900);///Вектор расширяется теперь до 6 элементов и 5 элементом записывается 900

     

    з.ы. уже вторая ошибка которую я нашел в уроках по векторам. Использую Visual Studio 2010. Может она не вкурсе c++11?

    • Melkom

      з.з.ы. vector:: shrink_to_fit() компилится нормально, значит студия вкурсе с++11…

      • NaikoN

        Попробуй скачать Visual Studio 2013 или друю IDE. Я проверял весь код, все норм работает и не каких глюков в приведенных примерах нету.

      • NaikoN

        Стандарт С++11 был введен только в Visual Studio 2012, т.к. он принят в 11 году, а Visual Studio 2010 вышда в 2010 году :)

        Стандарт С++11 даже в Visual Studio 2013 не реализован на все 100%.

      • eagle_vik

        eagle_vik

        да, у меня стояла Студия 2012 Максимальная, и то не полностью поддерживала С + +11, а скачал 2013 Экспресс и всё пашет… Найкон прав, там просто не полностью в 2012 реализован стандарт 11-й, но к 2013 студии пока претензий нет, всё что есть на сайте уже идёт без ошибок!

  4. NaikoN

    Map::emplase введен в стандарт С++11, отличие в том, если не ошибаюсь, что emplace -может вызвать нужный конструктор у создаваемого элемента. а insert — использует конструктор по умолчанию.

  5. Patrick

    Скажите, пожалуйста, а функции emplase и insert чем то отличаются? вроде выполняют одно и тоже…

Оставить комментарий

Вы должны войти, чтобы оставить комментарий.