34:	for (i = 0; i < dStrings.GetItemsInContainer(); i++ )
35:	cout << dStrings[i] << endl;		
36: 
37:	// Отобразить объекты контейнера с косвенным запоминанием		
38:	cout << endl;		
39:	cout << "Indirect string array" << endl;		
40:	for ( i = 0; i < iStrinfls.GetltemsInContainer(); i++ ) 
41:	  cout << *iStrings[i] << endl; 
42:		 
43:	return 0; 
44:	} 

    В программе объявляются два контейнера, способные запоминать объекты 
класса string, объявление которого содержится в заголовочном файле CSTRING.H. 
"Например, следующий оператор создает контейнер, запоминающий непосредственно 
сами объекты: 

    TArrayAsVector<string> dStrings(10); 

    Оператор, очень похожий на предыдущий, однако использующий другой 
класс, создает контейнер, который запоминает указатели на динамические строки, 
созданные с помощью оператора new: 

    TIArrayAsVector<string> iStrings(10); 

    Оба контейнера, dStrings и iStrings, обладают одинаковыми наборами функций 
и возможностями. Они различаются только тем, что в dStrings создается копия 
запоминаемой строки, а в iStrings запоминается указатель на строковый объект. 
    Далее программа запрашивает строку, которую помещает в символьный 
буфер. После использования буфера для создания строкового объекта s 
программа вставляет его в контейнер dStrings с помощью обращения к функции 
Add() контейнера класса: 

    dStrings.Add(s); 

    Функция Add() запоминает новый объект в массиве контейнера. Не все 
контейнерные классы снабжаются функцией AddO, но все контейнеры имеют как 
минимум один способ запоминания объектов. Для вставки строки в контейнер 
iString в программе используется оператор	

    iString.Add(new string(s)); 

    Было бы некорректно передавать адрес объекта s функции косвенного 
контейнера Add(). Строковая переменная s — только временный объект, который 
размещается в стеке программы. Передача адреса этого объекта косвенному 
контейнеру послужит причиной возникновения всевозможных проблем при 
уничтожении контейнера. Мораль сей басни такова — при использовании косвенных 
контейнеров всегда следует знать, где размещаются ваши объекты. Неплохо, 
например, воспользоваться оператором создания динамических строковых объектов 
new для запоминания их в контейнере.	 
    Поскольку в этом примере контейнерами служат массивы, они снабжаются 
функцией GetltemsInContainer(), сообщающей число сохраненных строк. В программе 
эта функция используется в цикле for для отображения объектов в контейнере с 
запоминанием непосредственно объектов:

    for (i=0;   i < dStrings.GetItemsInContainer();   i++)	
       cout « dStrings[i] « endl; 

    Отображение объектов в косвенном контейнере почти такое же, только 
необходимо разыменовывать элементы массива, поскольку все они — указатели:

    for ( i= 0 ;  i < iStrings.GetItemsInContainer();  i++) 
      cout << *iStrings[i] << endl;         // Обратите внимание на разыменование

    Удалите "звездочку" из последнего оператора, затем скомпилируйте заново и 
запустите программу на выполнение. Теперь будут выводиться адреса объектов, 
поскольку компилятор воспринимает iStrings[i] a качестве указателя на строку. 

    Итераторы 

    Итераторы предоставляют альтернативный метод доступа к объектам 
контейнера. Итераторами снабжаются абстрактные контейнеры вроде массивов и 
очередей, а также такие фундаментальные структуры, как списки и векторы. 
    С помощью итератора вы можете "передвигаться" по объектам в структуре без 
их удаления. Например, обычно только верхний объект стека доступен для 
просмотра, для получения же других объектов необходимо удалять их, вызывая 
функцию Рор(). С помощью итератора можно "передвигаться" по стеку для 
выполнения операций над его содержимым. 
    

    Глава 16. Библиотека шаблонов классов Borland	431 
