§2 Классы контейнеров. vector и array

(Ресурс помечен “на удаление”, другую версию урока (только vector) смотрите здесь)
  • Введение
  • Контейнеры — это специализированные классы, предназначенные для хранения однотипных объектов и обеспечения доступа к ним. Контейнер управляет выделяемой для его элементов памятью и предоставляет функции-члены для доступа к ним, либо непосредственного, либо через итераторы. Разные контейнеры обеспечивают различную эффективность тех или иных операций.
    Последовательные контейнеры STL vector и array, являются альтернативой встроенной структуре данных массиву (дальше будем называть такие массивы C-массивами).
    vector управляет элементами, хранящимися в динамическом массиве. Он обеспечивает произвольный доступ к элементам. Операции добавления элемента в конец массива и удаления элемента из конца массива выполняются очень быстро.
    array наиболее близок к С-массивам. Он хранит фиксированное число элементов, но поддерживает и дополнительный набор методов, в том числе и универсальных для всех контейнеров. Преимущество данного контейнера — максимально быстрый доступ к своих элементам.

  • Шаблонный класс array
  • Подключаемый заголовочный файл <array>.

    1. Объявление

    array<int, 10> mass1;
    

    В этом примере объявлен массив mass1, тип int, размером в 10 элементов. Поскольку в array количество элементов фиксировано, то эта величина не может быть переменной величиной.
    2. Инициализация итераторов
    Итераторы диапазона можно получить используя функции begin() и end(), но теперь (см. §1) как методы класса. Вместо указания конкретного типа можно использовать спецификатор auto.

    auto first = mass1.begin();
    auto last = mass1.end();
    

    3. Инициализация массива
    Списочная инициализация:

    array<int, 10> mass2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    

    Примечание. Списочную инициализацию можно использовать не только при объявлении. В таком случае, объявленный ранее массив, получит новые элементы.
    Заполнение определенным значением. Функция fill()

    array<int, 10> mass3;
    mass3.fill(2);
    

    Примечание. Добавление заголовка <algorithm> не требуется. Также доступна функция swap().
    Присваивание по имени элементов одного массива – другому. Количество элементов и тип данных должны быть равными.

    mass3 = mass2;
    

    Ввод и вывод элементов массива, используя традиционный подход с помощью оператора []. Для определения размера массива используется метод size(). Для доступа к элементам по индексу можно также использовать метод at (т. е. вместо mas[i], mas.at(i)), который осуществляет контроль выхода за границы массива. at(i) генерирует исключение out_of_range, если i > mas.size().

    #include <iostream>
    #include <array>
    #include <ctime>
    #include <cstdlib>
    using namespace std;
    
    int main() {
    	array<int, 20> mas;
    	srand(time(0));
    	for(auto i = 0; i < mas.size(); i++)
    		mas[i] = 10 + rand() % 90;
    	for(auto i = 0; i < mas.size(); i++)
    		cout << mas[i] << " ";
    
    	return 0;
    }
    

    Ввод и вывод элементов используя итераторы. (Работает быстрее, так как не пересчитываются индексы, как в предыдущем примере). Необходимо подключить заголовок <iterator>.

    #include <iostream>
    #include <array>
    #include <iterator>
    #include <ctime>
    #include <cstdlib>
    using namespace std;
    
    int main() {
    	array<int, 20> mas;
    	auto first = mas.begin();
    	auto last = mas.end();
    	srand(time(0));
    	while (first != last) {
    		*first = 10 + rand() % 90;
    		first++;
    	}
    	first = mas.begin();
    	while (first != last) {
    		cout << *first << " ";
    	first++;
    	}
    	return 0;
    }
    

    3. Цикл for, основанный на диапазоне. В примере ar – переменная цикла, которой передаются значения элементов массива mas.

    #include <iostream>
    #include <array>
    #include <ctime>
    #include <cstdlib>
    using namespace std;
    
    int main() {
    	array<int, 20> mas;
    	srand(time(0));
    	for (int &ar : mas)
    		ar = 10 + rand() % 90;
    	for (int &ar : mas)
    		cout << ar << " ";
    
    	return 0;
    }
    

    4. Операции сравнения. Метод empty
    Для array определены операции сравнения ==, !=, <, <=, >, >=

    return mas1 > mas2 ? true : false;
    

    Метод empty вернет булевский результат проверки на предмет наличия элементов в контейнере (т. е. является ли begin() == end())

  • Шаблонный класс vector
  • Подключаемый заголовочный файл <vector>.

    1. Объявление, инициализация и вывод
    Описание массива vector отличается от array:

    vector<int> mass(n);
    

    В этом примере объявлен массив mass, типа int, с размером n элементов (переменная n определена в программе раньше, см. пример ниже). Все действия с массивам array, изложенные выше, схожи с массивом vector, поэтому здесь мы повторяться не будем.

    #include <iostream>
    #include <vector>
    #include <iterator>
    #include <ctime>
    #include <cstdlib>
    using namespace std;
    
    int main() {
    	int n;
    	cout << "n = "; cin >> n;
    	vector<int> mass(n);
    	auto first = mass.begin();
    	auto last = mass.end();
    	while (first != last) {
    		*first = 10 + random() % 90;
    		first++;
    	}
    	for (auto &ar : mass)
    		cout << ar << " ";
    	cout << endl;
    
    	return 0;
    }
    

    2. Инициализация массива vector элементами другого массива

    int arr1[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    vector<int> mass1(arr1, arr1 + 10);
    for (auto &ar : mass1)
    	cout << ar << " ";
    

    Значения элементов одного вектора можно инициализировать значениями элементов другого.

    vector<int> mass2(mass1);
    

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

    vector<int> mass(20, 3);
    

    20 элементов массива будут иметь значение 3.

    Главное отличие массива vector от массива array в том, что первый инкапсулирует массивы переменного размера, т. е. динамические массивы. Хранилище вектора обрабатывается автоматически, расширяясь и сужаясь по мере необходимости. Вектор обычно занимает больше места, чем статические массивы, потому что некоторое количество памяти выделяется на обработку будущего роста. Общий объём выделенной памяти можно получить с помощью функции capacity(). Дополнительная память может быть возвращена системе через вызов shrink_to_fit().

  • Модификаторы
  • clear()
    Метод clear() (без параметров) очищает контейнер (удаляет все элементы). Проверить пуст ли контейнер можно методом empty().

    mass.clear();
    if (mass.empty()) cout << true << endl;
    

    insert() и erase()
    Методы insert() и erase() вставляют и удаляют элементы в произвольной позиции. Эти методы не рекомендуется использовать для массива vector ввиду неэффективности, так как при вставке и удалении происходит перераспределение памяти.
    Вставить элемент, имеющий значение value, в позицию it:

    mass.insert(it, value);
    

    Удалить элемент в позиции it:

    mass.erase(it)
    

    push_back() и pop_back()
    Метод push_back() вставляет элемент в конец, а pop_back() удаляет последний элемент.
    Использование:

    mass.push_back(value)
    mass.pop_back()
    

    Постановка задачи. Дан пустой массив vector. Заполнить массив случайными числами используя метод push_back().

    #include <iostream>
    #include <vector>
    #include <ctime>
    #include <cstdlib>
    using namespace std;
    
    int main() {
    	vector<int> mass;
    	for (int i = 1; i <= 20; i++) {
    		mass.push_back(10 + random() % 90);
    	}
    	cout << endl;
    	for (auto &ar : mass)
    		cout << ar << " ";
    
    	return 0;
    }
    

    resize()
    Метод resize() изменяет размер контейнера. Использование:

    mass.resize(count, value)
    

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

    swap()
    Метод производит обмен элементов между двумя массивами vector:

    mass1.swap(mass2)
    

    assign()
    Метод assign() заменяет содержимое контейнера.

    mass.assign(count, value)
    mass.assign(first, last)
    

    В первом случае заменяется count копиями значений value. Во втором копиями элементов из диапазона [first, last).

Print Friendly, PDF & Email

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