Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих (Стенли Липпман) 3-е хххх.pdf
Скачиваний:
86
Добавлен:
30.05.2015
Размер:
5.92 Mб
Скачать

С++ для начинающих

119

3.10. Класс vector

Использование класса vector (см. раздел 2.8) является альтернативой применению встроенных массивов. Этот класс предоставляет гораздо больше возможностей, поэтому его использование предпочтительней. Однако встречаются ситуации, когда не обойтись без массивов встроенного типа. Одна из таких ситуаций обработка передаваемых программе параметров командной строки, о чем мы будем говорить в разделе 7.8. Класс vector, как и класс string, является частью стандартной библиотеки С++.

Для использования вектора необходимо включить заголовочный файл:

#include <vector>

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

vector< int > ivec( 10 );

что аналогично определению массива встроенного типа:

int ia[ 10 ];

void simp1e_examp1e()

{

const int e1em_size = 10; vector< int > ivec( e1em_size ); int ia[ e1em_size ];

for ( int ix = 0; ix < e1em_size; ++ix ) ia[ ix ] = ivec[ ix ];

// ...

Для доступа к отдельным элементам вектора применяется операция взятия индекса:

}

Мы можем узнать размерность вектора, используя функцию size(), и проверить, пуст ли

void print_vector( vector<int> ivec )

{

if ( ivec.empty() ) return;

for ( int ix=0; ix< ivec.size(); ++ix ) cout << ivec[ ix ] << ' ';

вектор, с помощью функции empty(). Например:

}

Элементы вектора инициализируются значениями по умолчанию. Для числовых типов и указателей таким значением является 0. Если в качестве элементов выступают объекты

С++ для начинающих

120

класса, то инициатор для них задается конструктором по умолчанию (см. раздел 2.3). Однако инициатор можно задать и явно, используя форму:

vector< int > ivec( 10, -1 );

Все десять элементов вектора будут равны -1.

Массив встроенного типа можно явно инициализировать списком:

int ia[ 6 ] = { -2, -1, О, 1, 2, 1024 };

Для объекта класса vector аналогичное действие невозможно. Однако такой объект

// 6 элементов ia копируются в ivec

может быть инициализирован с помощью массива встроенного типа: vector< int > ivec( ia, ia+6 );

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

// копируются 3 элемента: ia[2], ia[3], ia[4]

указать не весь массив, а некоторый его диапазон: vector< int > ivec( &ia[ 2 ], &ia[ 5 ] );

Еще одним отличием вектора от массива встроенного типа является возможность инициализации одного объекта типа vector другим и использования операции

vector< string > svec;

void init_and_assign()

{

//один вектор инициализируется другим vector< string > user_names( svec );

//...

//один вектор копируется в другой svec = user_names;

присваивания для копирования объектов. Например:

}

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

vector< string > text;

6 STL расшифровывается как Standard Template Library. До появления стандартной библиотеки С++ классы vector, string и другие, а также обобщенные алгоритмы входили в отдельную библиотеку с названием STL.

С++ для начинающих

121

Затем добавляем к нему элементы при помощи различных функций. Например, функция push_back()вставляет элемент в конец вектора. Вот фрагмент кода, считывающего

string word;

while ( cin >> word ) { text.push_back( word ); // ...

последовательность строк из стандартного ввода и добавляющего их в вектор:

}

cout << "считаны слова: \n";

for ( int ix =0; ix < text.size(); ++ix ) cout << text[ ix ] << ' ';

Хотя мы можем использовать операцию взятия индекса для перебора элементов вектора: cout << endl;

cout << "считаны слова: \n";

for ( vector<string>::iterator it = text.begin(); it != text.end(); ++it )

cout << *it << ' ';

более типичным в рамках данной идиомы будет использование итераторов: cout << endl;

Итератор это класс стандартной библиотеки, фактически являющийся указателем на элемент массива.

Выражение

*it;

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

++it;

сдвигает указатель на следующий элемент. Не нужно смешивать эти два подхода. Если следовать идиоме STL при определении пустого вектора:

vector<int> ivec;

будет ошибкой написать:

ivec[0] = 1024;

У нас еще нет ни одного элемента вектора ivec; количество элементов выясняется с помощью функции size().

С++ для начинающих

122

Можно допустить и противоположную ошибку. Если мы определили вектор некоторого размера, например:

vector<int> ia( 10 );

то вставка элементов увеличивает его размер, добавляя новые элементы к существующим. Хотя это и кажется очевидным, тем не менее, начинающий программист

const int size = 7;

int ia[ size ] = { 0, 1, 1, 2, 3, 5, 8 }; vector< int > ivec( size );

for ( int ix = 0; ix < size; ++ix )

вполне мог бы написать: ivec.push_back( ia[ ix ] );

Имелась в виду инициализация вектора ivec значениями элементов ia, вместо чего получился вектор ivec размера 14.

Следуя идиоме STL, можно не только добавлять, но и удалять элементы вектора. (Все это мы рассмотрим подробно и с примерами в главе 6.)

Упражнение 3.24

int ia[ 7 ] = { 0, 1, 1, 2, 3, 5, 8 };

(a)vector< vector< int > > ivec;

(b)vector< int > ivec = { 0, 1, 1, 2, 3, 5, 8 };

(c)vector< int > ivec( ia, ia+7 );

(d)vector< string > svec = ivec;

Имеются ли ошибки в следующих определениях?

(e) vector< string > svec( 10, string( "null" ));

Упражнение 3.25

bool is_equa1( const int*ia, int ia_size,

Реализуйте следующую функцию:

const vector<int> &ivec );

Функция is_equal() сравнивает поэлементно два контейнера. В случае разного размера контейнеров хвостболее длинного в расчет не принимается. Понятно, что, если все сравниваемые элементы равны, функция возвращает true, если отличается хотя бы один false. Используйте итератор для перебора элементов. Напишите функцию main(), обращающуюся к is_equal().

3.11. Класс complex

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