itmo.ru aco.ifmo.ru c-visionlab.ru
вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


3.3. Вектор vector (пример 3.3)

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

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

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

#include <vector>
using namespace std;

vector<double> x; // создание вектора
 
x.resize(10); // изменение размера вектора
x.resize(x.size()+100); // изменение размера вектора

double sum=0.0;
for(int i=0; i<x.size(); i++)
{
    sum+=x[i]; //доступ по индексу
}

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

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

/////////////////////////////////////////////////////////////////////////////
// Программирование на языке высокого уровня. Основы языка С++
// Пример 3.3. Пример работы с контейнером vector
// 
// http://aco.ifmo.ru/el_books/programming
// Университет ИТМО
/////////////////////////////////////////////////////////////////////////////
#include <iostream>   // подключение библиотеки ввода-вывода
#include <vector>     // подключение описания вектора
#include <ctime>      // для работы с таймером
using namespace std;  // подключение стандартного пространства имен для использования библиотек

// прототипы функций 
int min(const vector<double>& data);
void fill_rand(vector<double>& data, double max, double min);
/////////////////////////////////////////////////////////////////////////////
// пример передачи вектора в функцию
// функция находит индекс минимального числа в векторе
int min(const vector<double>& data)
{
    int index=0;
    double min=data[0];
    for(int i=1; i<data.size(); ++i)
    {
        if(data[i]<min)
        {
            min=data[i];
            index=i;
        }
    }
    return index;
}
/////////////////////////////////////////////////////////////////////////////
// Функция заполнения вектора случайными числами
// data - вектор для заполнения
// max - максимальное число случайного диапазона
// min - минимальное число случайного диапазона
void fill_rand(vector<double>& data, double max, double min)
{
    // устанавливает стартовую точку для генерации
    // случайных чисел по текущему времени
    srand((unsigned) clock());
    for(int i=0; i<data.size(); ++i)
    {
        data[i]=(rand()*(max-min))/RAND_MAX+min;
    }
}
/////////////////////////////////////////////////////////////////////////////
void main()
{
    vector<double> x; // создание вектора

    // ввод количества элементов в векторе
    int n;   
    cout<<"input vector size: ";
    cin>>n;

    // 1. заполнение контейнера индексами
    // заполнение контейнера
    for(int i=0; i<n; i++)
    {
        // добавить элемент в конец контейнера 
        x.push_back(i); 
    }
    // вывод всех элементов контейнера
    cout<<endl<<"1. Vector filled with indexes: "<<endl;
    for(int i=0; i<x.size(); i++)
    {
        cout<<x[i]<<" "; //доступ по индексу
    }

    // 2. заполнение контейнера случайными числами от 1 до 100
    // очистить контейнер 
    x.clear();
    // изменить размер
    x.resize(20);    
    // заполнить случайными числами
    fill_rand(x, 1, 100);
    // вывод всех элементов контейнера
    cout<<endl<<"2. Vector filled with random: "<<endl;
    for(int i=0; i<x.size(); i++)
    {
        cout<<x[i]<<endl; //доступ по индексу
    }
    // вывод минимального числа в контейнере
    cout<<endl<<"mininum is: "<<x[min(x)]<<endl; // 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().