// первый неравный элемент: 5, 9
ivecl ivec3 //true
// все элементы равны, но ivec4 содержит меньше элементов
// следовательно, ivec4 меньше, чем ivecl
ivecl ivec4 //false
// первый неравный элемент: 1, 2
ivecl ivec5 //true
ivecl == ivecl //true
ivecl == ivec4 //false
ivecl != ivec4 //true
ivecl ivec2 //true
ivec3 ivecl //true
ivec5 ivec2 //true
Существуют три ограничения на тип элементов контейнера (практически это касается только пользовательских классов). Для должны быть определены:
* операция “равно”;
* операция “меньше” (все операции сравнения контейнеров, о которых говорилось выше, используют только эти две операции сравнения);
* значение по умолчанию (для класса это означает наличие конструктора по умолчанию).
Все предопределенные типы данных, включая указатели и классы из стандартной библиотеки С++ удовлетворяют этим требованиям.
Объясните, что делает данная программа:
#include string
#include vector
#include iostream
#int main()
{
vectorstring svec;
svec.reserve( 1024 );
string text_word;
while ( cin text_word )
svec.push_back( text_word );
svec.resize( svec.size()+svec.size()/2 );
// ...
}
Может ли емкость контейнера быть меньше его размера? Желательно ли, чтобы емкость была равна размеру: изначально или после вставки элемента? Почему?
Если программа из упражнения 6.5 прочитает 256 слов, то какова наиболее вероятная емкость контейнера после изменения размера? А если она считает 512 слов? 1000? 1048?
Какие из данных классов не могут храниться в векторе:
(a)
class cl1 {
public:
c11( int=0 );
bool operator==();
bool operator!=();
bool operator=();
bool operator();
// ...
};
(b)
class c12 {
public:
c12( int=0 );
bool operator!=();
bool operator=();
// ...
};
(с)
class c13 {
public:
int ival;
};
(d)
class c14 {
public:
c14( int, int=0 );
bool operator==();
bool operator!=();
// ...
}
6.5. Итераторы
Итератор предоставляет обобщенный способ перебора элементов любого контейнера – как последовательного, так и ассоциативного. Пусть iter является итератором для какого-либо контейнера. Тогда
++iter;
перемещает итератор так, что он указывает на следующий элемент контейнера, а
*iter;
разыменовывает итератор, возвращая элемент, на который он указывает.
Все контейнеры имеют функции-члены begin() и end().
* begin() возвращает итератор, указывающий на первый элемент контейнера.
* end() возвращает итератор, указывающий на элемент, следующий за последним в контейнере.
Чтобы перебрать все элементы контейнера, нужно написать:
for ( iter = container. begin();
iter != container.end(); ++iter )
do_something_with_element( *iter );
Объявление итератора выглядит слишком сложным. Вот определение пары итераторов вектора типа string:
// vectorstring vec;
vectorstring::iterator iter = vec.begin();
vectorstring::iterator iter_end = vec.end();
В классе vector для определения iterator используется typedef. Синтаксис
vectorstring::iterator
ссылается на iterator, определенный с помощью typedef внутри класса vector, содержащего элементы типа string.
Для того чтобы напечатать все элементы вектора, нужно написать:
for( ; iter != iter_end; ++iter )
cout *iter '\n';
Здесь значением *iter выражения является, конечно, элемент вектора.
В дополнение к типу iterator в каждом контейнере определен тип const_iterator, который необходим для навигации по контейнеру, объявленному как const. const_iterator позволяет только читать элементы контейнера:
#include vector
void even_odd( const vectorint *pvec,
vectorint *pvec_even,
vectorint *pvec_odd )
{
// const_iterator необходим для навигации по pvec
vectorint::const_iterator c_iter = pvec-begin();