Г. Шилтд - Самоучитель C++ (PDF) (1114887), страница 64
Текст из файла (страница 64)
s i z e O « endl;430_СамоучительC++/I вывод на экран содержимого вектора vcout « "Текущее содержимое: \п";for(i=0; i<v.size{); i++) cout « v[i] « " ";cout « endl;// помещение новых значений в конец вектора,/ / и опять по мере необходимости вектор будет растиfor(i=0; i<10; i++) v.push_back (i+10) ;// вывод на экран текущего размера вектораcout « "Новый размер = " « v. size О « endl;// вывод на экран содержимого вектораcout « "Текущее содержимое: \п";for(i=0; i<v.size(); i4+) cout « v[i] « " ";cout « endl;// изменение содержимого вектораfor(i=0; i<v. sized; i++) v[i] = v[i] + v[i];// вывод на экран содержимого вектораcout « "Удвоенное содержимое : \п" ;for(i=0; i<v.size(); i++) cout « v[i] « " ";cout « endl;return 0 ;После выполнения программы на экране появится следующее:Размер = ОНовый размер = 10Текущее содержимое:0 1 2 3 4 5 6 7 8 9Новый размер = 20Текущее содержимое:О 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19Удвоенное содержимое:О 2 4 б 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38Тщательно проанализируйте программу.
В функции main() создается вектор vдля хранения целых. Поскольку не используется никакой инициализации, этопустой вектор с равной нулю начальной емкостью, то есть это вектор нулевойдлины. Этот факт подтверждается вызовом функции-члена size(). Далее с помощью функции-члена push_back() к концу вектора v добавляется десять элементов.
Чтобы разместить эти новые элементы, вектор v вынужден увеличиться. Как показывает выводимая на экран информация, его размер стал равным10. После этого выводится содержимое вектора v. Обратите внимание, что дляэтого используется обычный оператор индекса массива. Далее к вектору добав-Глава14.Библиотекастандартныхшаблонов_43?ляется еще десять элементов и, чтобы их разместить, вектор снова автоматически увеличивается. В конце концов, с помощью стандартного оператора индекса массива меняются значения элементов вектора.В программе есть еще кое-что интересное.
Отметьте, что функция v.sizeQуказана прямо в инструкции организации цикла вывода на экран содержимого вектора v. Одним из преимуществ векторов по сравнению с массивамиявляется то, что вы всегда имеете возможность определить текущий размервектора. Очевидно, что такая возможность может оказаться полезной в самых разных ситуациях,2. Как вы знаете, в C++ массивы и указатели очень тесно связаны. Доступ кмассиву можно получить либо через оператор индекса, либо через указатель.По аналогии с этим в библиотеке стандартных шаблонов имеется теснаясвязь между векторами и итераторами.
Доступ к членам вектора можно получить либо через оператор индекса, либо через итератор. В следующем примере показаны оба этих подхода.// Организация доступа к вектору с помощью итератора^include <iostream>^include <vector>using namespace std;int main { }{vector<int> v; // создание вектора нулевой длиныint i;// помещение значений в векторfor (1=0; К10; 1+-Н v,push_back (i) ;// доступ к содержимому вектора// с использованием оператора индексаfor{i=0; i<10; i++) cout « v[i] « " ";cout « endl;// доступ к вектору через итераторvector<int>: : iterator p = v.beginO;while{p != v.end)} {cout « *p « " ";P++;return 0;После выполнения программы на экране появится следующее:0 1 2 3 4 5 6 7 8 90 1 2 3 4 5 6 7 8 9432Самоучитель C++В этой программе тоже сначала создается вектор v нулевой длины.
Далее спомощью функции-члена push_back() к концу вектора v добавляются некоторые значения и размер вектора v увеличивается.Обратите внимание на объявление итератора р. Тип iterator определяется спомощью класса-контейнера. То есть, чтобы получить итератор для выбранного контейнера, объявить его нужно именно так, как показано в примере:просто укажите перед типом iterator имя контейнера. С помощью функциичлена beginQ итератор инициализируется, указывая на начало вектора. Возвращаемым значением этой функции как раз и является итератор начала вектора.
Теперь, применяя к итератору оператор инкремента, можно получитьдоступ к любому выбранному элементу вектора. Этот процесс совершенноаналогичен использованию указателя для доступа к элементам массива. Спомощью функции-члена end() определяется факт достижения конца вектора.
Возвращаемым значением этой функции является итератор того места,которое находится сразу за последним элементом вектора, Таким образом,если итератор р равен возвращаемому значению функции v.end(), значит, конец вектора был достигнут.3. Помимо возможности размещения элементов в конце вектора, с помощьюфункции-члена insert() их можно вставлять в его середину.
Удалять элементыиз вектора можно с помощью функции-члена erase().// Демонстрация функций insert() и erase ()tinclude <iostream>^include <vector>using namespace std;int(main()vector<int> v(5, 1); // создание пятиэлементного вектора//из единицint i;// вывод на экран исходных размера и содержимого вектораcout « "Размер = " « v.sizef) « endl;cout « "Исходное содержимое:\п";for(i=0; i<v.size(}; !+•<-) cout « v[i] « " ";cout « endl;vector<int>::iterator p = v.begin{);p += 2; // указывает на третий элемент// вставка в вектор на то место,// куда указывает итератор р десяти новых элементов,// каждый из которых равен 9v.insert(p, 10, 9) ;// вывод на экран размера//и содержимого вектора после вставкиcout « "Размер после вставки = " « v.sizeO « endl;Глава 14.
Библиотека стандартных шаблонов433cout « "Содержимое после вставки:\п";for(i=0; i < v . s i z e ( ) ; i++) cout « v[i] « " ";cout « endl;// удаление вставленных элементовp = v.begin () ;p += 2; // указывает на третий элементv.erase{p, р-ЫО); // удаление следующих десяти элементов// за элементом, на который указывает// итератор р// вывод на экран размера,,// и содержимого вектора после удаленияcout « "Размер после удаления — " « v.sizeO « endl;cout « "Содержимое после удаления:\п";for{i=0; i<v.size(); i++) cout « v[i] « " ";cout « endl;return 0;После выполнения программы на экране появится следующее:Размер = 5Исходное содержимое:11111Размер после вставки = 15Содержимое после вставки:1 1 9 9 9 9 9 9 9 9 9 9 1 1 1Размер после удаления = 5Содержимое после удаления:111114. В следующем примере вектор используется для хранения объектов класса,определенного программистом.
Обратите внимание, что в классе определяются конструктор по умолчанию и перегруженные версии операторов < и==. Помните, в зависимости от того, как реализована библиотека стандартных шаблонов для вашего компилятора, вам может понадобиться определитьи другие операторы сравнения.// Хранение в векторе объектов пользовательского класса#include <iostream>#include <vector>using namespace std;class Demo {double d;Самоучитель C++434public:Demo () { d = 0.0; }Demo (double x) { d = x; }Demo ^operator- (double x) (d = x; return ''this;}double getd() (return d; }boll operator< (Demo a, Demo b){return a.getdf) < b.getdf);1boll operator— (Demo a, Demo b}{return a.getd() == b.getdO;}int mainO{vector<Demo> v;int i;for{i=0; iv.push_back(Demo (i/3. 0) ) ;for (i=0; Kv.size () ; icout « v [ i ] .
g e t d ( ) « " ";cout « endl;for(i=0; i < v . s i z e ( } ; i++)v[i] = v[i] .getdO * 2.1;for (i=0; Kv.size () ; icout « v [ i ] . g e t d ( ) « " ";return 0;После выполнения программы на экране появится следующее:О 0.333333 0 . 6 6 6 6 6 7 1 1.33333 1.66667 2 2.33333 2 . 6 6 6 6 7 3О 0.7 1.4 2.1 2.8 3.5 4.2 4.9 5.6 6.3Упражненияения]1. Поэкспериментируйте с представленными примерами. Попытайтесь делатьнебольшие изменения в программах и исследуйте результаты.Глава 14. Библиотека стандартных шаблонов4352. В примере 4 для класса Demo были определены два конструктора — конструктор по умолчанию (конструктор без параметров) и конструктор с параметрами. Сможете ли вы объяснить, почему это так важно?3.
Ниже представлен пример класса Coord. Напишите программу для храненияобъектов типа Coord в векторе. (Подсказка: не забудьте для класса Coord определить операторы < и ==.)class Coord (public:int x, у;Coord(} { x = у = 0; }Coord(int a, int b) { x = а; у = b;}14.4. СпискиКласс list поддерживает двунаправленный линейный список. В отличии отвектора, в котором реализован произвольный доступ, к элементам спискадоступ может быть только последовательным. Поскольку списки являютсядвунаправленными, доступ к элементам списка возможен с обеих его сторон.Ниже представлена спецификация шаблона для класса list:template<class T r class Allocator = allocator<T»class listЗдесь Т — это тип данных, предназначенных для хранения в списке, а ключевое слово Allocator задает распределитель памяти, который по умолчаниюявляется стандартным распределителем памяти. В классе list определеныследующие конструкторы:explicit list(const Allocator Sa — Allocator());explicit list (size_type число, const Т &аначение = TO fconst Allocator &a = Allocator{));list(const list<T, Allocator>£объект);template<class Inlter>list{Inlter на«ало, Inlter конец,const Allocator fia = Allocator<));Первая форма представляет собой конструктор пустого списка.
Вторая форма — конструктор списка, число элементов которого — это число, а каждыйэлемент равен значению значение, которое может быть значением по умолчанию. Третья форма конструктора предназначена для списка из одинаковых элементов, каждый из которых — это объект. Четвертая форма — этоконструктор списка, содержащего диапазон элементов, заданный итераторами начало и конец.Самоучитель C++436Для класса list определяются следующие операторы сравнения:==, <, <=, г=, >, >=В табл. 14.3 представлены функции — члены класса list. Размешать элементы в конце списка можно с помощью функции pushJbackQ (как и в случае свектором), в начале — с помощью функции push_front(), а в середине — спомощью функции insert().