На этом шаге мы рассмотрим еще один пример использования класса auto_ptr.
Следующий пример демонстрирует поведение константных объектов auto_ptr.
//--------------------------------------------------------------------------- #include <vcl.h> #include <iostream> #include <memory> #include <winuser.h> #include <conio.h> //необходимо для getch() #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused using namespace std; std::string ToRus(const std::string &in) { char *buff = new char [in.length()+1]; CharToOem(in.c_str(),buff); std::string out(buff); delete [] buff; return out; } // Определение оператора вывода для auto_ptr // - вывод значения объекта или NULL template <class T> ostream& operator<< (ostream& strm, const auto_ptr<T>& p) { // Указывает ли р на объект? if (p.get() == NULL) { strm << "NULL"; // НЕТ: вывести строку NULL } else { strm << *p; // ДА: вывести объект } return strm; } int main(int argc, char* argv[]) { const auto_ptr <int> p(new int(42)); const auto_ptr <int> q(new int(0)); const auto_ptr <int> r; cout << ToRus("После инициализации:") << endl; cout <<" p: " << p << endl; cout <<" q: " << q << endl; cout <<" r: " << r << endl; *q = *p; // ОШИБКА: неопределенное поведение // *r = *p; *p = -77; cout << ToRus("После придания значений:") << endl; cout <<" p: " << p << endl; cout <<" q: " << q << endl; cout <<" r: " << r << endl; // ОШИБКА компиляции // q = p; // ОШИБКА компиляции // r = p; getch(); return 0; } //---------------------------------------------------------------------------
Результат выполнения программы:
Рис.1. Результат работы приложения
В примере определен оператор вывода для auto_ptr, при этом объект auto_ptr передается по константной ссылке. Как упоминалось на шаге 62, передавать auto_ptr функциям не рекомендуется; данная функция является исключением.
Обратите внимание: следующее присваивание является ошибкой:
*r = *р;
В этом присваивании производится разыменование экземпляра auto_ptr, не ссылающегося на объект. В соответствии со стандартом это приводит к непредсказуемым последствиям (например, аварийному завершению программы). Как показывает приведенный пример, вы можете работать с объектами, на которые ссылается константный указатель auto_ptr, но не можете изменять принадлежащие им объекты. Даже если бы переменная r была объявлена неконстантной, последняя команда была бы невозможной из-за модификации константы р.
Со следующего шага мы дадим подробное описание класса auto_ptr.