Читайте также:
|
|
Класс auto_ptr – это шаблонный класс для контроля над распределением динамической памяти.
void remodel (string & str)
{
string * ps = new string(str);
str = ps;
return;
}
При каждом вызове функции происходит выделение памяти в куче, однако память не освобождается. Это приводит к утечкам памяти. Решение проблемы очевидно – не забыть освободить память:
delete ps;
перед оператором return. Однако, решение, которое содержит фразу "не забыть", не является идеальным. Иногда разработчик не желает помнить об этом. Или разработчик помнит, но случайно удалил или закомментировал строку. И даже в том случае, когда это решение используется, могут возникать проблемы.
void remodel(string & str)
{
string * ps = new string (str);
if (weird_thing())
throw exception();
str = *ps;
delete ps;
return;
}
При возникновении исключительной ситуации операция delete вообще не будет достигнута, и снова появится утечка памяти.
Такие ошибки исправимы, но желательно иметь лучшее решение. Программа должна выполнять некоторые дополнительные действия после удаления указателя. В базовых типах подобной функциональности нет. Для классов такая возможность предоставлена через деструкторы. Если бы ps был объектом, то деструктор бы освобождал память, на которую указывал объект, при удалении объекта. Это и есть основная идея использования auto_ptr.
Шаблон аutо_рtr определяет объект, которому присваивается адрес области памяти, полученный вызовом операции new. Когда объект auto_ptr удаляется, его деструктор использует delete для освобождения памяти. Таким образом, присвоив адрес, возвращаемый операцией new, объекту auto_ptr, не нужно беспокоиться о последующем высвобождении памяти. Это будет сделано автоматически, при удалении объекта.
Для создания объекта auto_ptr необходимо включить заголовочный файл memory, в котором содержится шаблон auto_ptr. После этого, используя обычный синтаксис шаблонов, можно создавать указатели нужного типа. Интеллектуальные указатели принадлежати типу std.
template <class Х>
class auto_ptr
{
public:
explicit auto_ptr (X* р =0) throw(); // конструктор не должен генерировать исключения
...
};
Auto_ptr<double> pd(new double);
Auto_ptr<string> ps(new string);
Допустимо только явное преобразование их простого указателя в интеллектуальный.
Недопустимо:
String helloStr(“Hello”);
auto_ptr<string> pHello(&helloStr);
В С++11 шаблон auto_ptr объявлен устаревшим, в качестве альтернативы предлагаются shared_ptr и unique_ptr.
Auto_ptr:
auto_ptr<string> p1(new string(“OOP”));
auto_ptr<string> p2;
p2=p1
cout << p1 // p1 утрачивает право владения указателем и перестает ссылаться на строку. Может привести к Segmentation fault (core dump).
Shared_ptr:
shared_ptr<string> p1(new string(“OOP”));
shared_ptr<string> p2;
p2=p1
cout << p1 //операция завершится успешно, т.к. p1и p2 указывают на один и тот же объект. Используется стратегия подсчета ссылок. При p1=p2 значение счетчика ссылок увеличилось на 1. В конце программы сначала вызовется деструктур p2, который уменьшит количество ссылок на 1. delete выполнится, когда счетчик ссылок станет 0.
Unique_ptr:
unique_ptr<string> p1(new string(“OOP”));
unique_ptr<string> p2;
p2=p1 // будет сгенерирована ошибка во время компиляции
Но если программа пытается присвоить один объект unique_ptr другому, компилятор не препятствует этому, если исходный объект является временным значением, и запрещает это, если исходный объет существует некоторое время.
Auto_ptr и shared _ ptr не могут использоваться с массивами (память, выделенная как new[]). Unique_ptr может использоваться как с объектами, память для которых выделена операцией n ew, так и с объектами, память для которых выделена операцией new[].
Дата добавления: 2015-11-16; просмотров: 66 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Типичные ошибки при работе со ссылками | | | Перегрузка операторов преобразования типа |