<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://mit.spbau.ru/sewiki/index.php?action=history&amp;feed=atom&amp;title=%D0%A3%D0%BC%D0%BD%D1%8B%D0%B5_%D1%83%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D0%B8_C%2B%2B</id>
		<title>Умные указатели C++ - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://mit.spbau.ru/sewiki/index.php?action=history&amp;feed=atom&amp;title=%D0%A3%D0%BC%D0%BD%D1%8B%D0%B5_%D1%83%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D0%B8_C%2B%2B"/>
		<link rel="alternate" type="text/html" href="http://mit.spbau.ru/sewiki/index.php?title=%D0%A3%D0%BC%D0%BD%D1%8B%D0%B5_%D1%83%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D0%B8_C%2B%2B&amp;action=history"/>
		<updated>2026-05-05T14:30:25Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>http://mit.spbau.ru/sewiki/index.php?title=%D0%A3%D0%BC%D0%BD%D1%8B%D0%B5_%D1%83%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D0%B8_C%2B%2B&amp;diff=2264&amp;oldid=prev</id>
		<title>Smal: Новая страница: «== Введение == Умные указатели (УА) ([http://en.wikipedia.org/wiki/Smart_pointers smart pointers]) используюу принцип &quot;''[ht…»</title>
		<link rel="alternate" type="text/html" href="http://mit.spbau.ru/sewiki/index.php?title=%D0%A3%D0%BC%D0%BD%D1%8B%D0%B5_%D1%83%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D0%B8_C%2B%2B&amp;diff=2264&amp;oldid=prev"/>
				<updated>2013-03-20T12:18:20Z</updated>
		
		<summary type="html">&lt;p&gt;Новая страница: «== Введение == Умные указатели (УА) ([http://en.wikipedia.org/wiki/Smart_pointers smart pointers]) используюу принцип &amp;quot;&amp;#039;&amp;#039;[ht…»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Введение ==&lt;br /&gt;
Умные указатели (УА) ([http://en.wikipedia.org/wiki/Smart_pointers smart pointers])&lt;br /&gt;
используюу принцип &amp;quot;''[http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D0%B0_%D0%B5%D1%81%D1%82%D1%8C_%D0%B8%D0%BD%D0%B8%D1%86%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F Получение ресурса есть инициализация]''&amp;quot; ([http://en.wikipedia.org/wiki/RAII RAII]) для автоматизации управления памятью.&lt;br /&gt;
Использование правильного умного указателя упростит и обезопасит ваш код, а так же поможет избежать memory leak-ов.&lt;br /&gt;
&lt;br /&gt;
=== Виды умных указателей ===&lt;br /&gt;
Умные указатели можно разделить на три вида:&lt;br /&gt;
* с безраздельным владением:&lt;br /&gt;
** std::auto_ptr&lt;br /&gt;
** boost::scoped_ptr&lt;br /&gt;
** boost::scoped_array&lt;br /&gt;
&lt;br /&gt;
* с раздельным владением:&lt;br /&gt;
** boost::shared_ptr&lt;br /&gt;
** boost::shared_array&lt;br /&gt;
** boost::intrusive_ptr&lt;br /&gt;
&lt;br /&gt;
== Умные указатели с безраздельным владением ==&lt;br /&gt;
Умные указатели этого вида предназначены для хранения на стэке или для включения в класс.&lt;br /&gt;
&lt;br /&gt;
Особняком в этом классе держится std::auto_ptr. С него и начнем.&lt;br /&gt;
&lt;br /&gt;
=== std::auto_ptr ===&lt;br /&gt;
std::auto_ptr спроектирован для того, чтобы сделать код безопасным с точки зрения исключений.&lt;br /&gt;
Использование std::auto_ptr позволяет писать код, который отвечает строгой гарантии относительно&lt;br /&gt;
исключений ([http://en.wikipedia.org/wiki/Exception_handling strong exception guarantee]). Подробное&lt;br /&gt;
описание того, как с помощью std::auto_ptr сделать Ваш код безопасным нужно читать в книге Герба Саттера&lt;br /&gt;
[http://www.books.ru/shop/books/30998 &amp;quot;Решение сложных задач на C++&amp;quot;] (вторая глава).&lt;br /&gt;
&lt;br /&gt;
Основное отличие std::auto_ptr от умных указателей с безраздельным владением заключается в наличии у него&lt;br /&gt;
конструктора копирования, оператора присваивания и метода release.&lt;br /&gt;
При копировании (как и при присваивании) std::auto_ptr передает владение объектом, а метод release()&lt;br /&gt;
позволяет явно отобрать владение объектом у std::auto_ptr.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
std::auto_ptr&amp;lt;A&amp;gt; p1, p2;&lt;br /&gt;
p1.reset( new A() ); // p1 владеет A, p2 == NULL&lt;br /&gt;
p2 = p1; // p1 передает владение p2. Теперь p1 == NULL, а p2 владеет A&lt;br /&gt;
std::auto_ptr&amp;lt;A&amp;gt; p3(p2); // p2 передает владение p3&lt;br /&gt;
A * p4 = p3.release(); // p3 передает владение p4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Такое поведение позволяет безопасно передавать в функцию и возвращать из функции объекты, которые могут бросать&lt;br /&gt;
исключения при копировании, а также избегать ликов.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
std::auto_ptr&amp;lt;A&amp;gt; foo(int a)&lt;br /&gt;
{&lt;br /&gt;
return std::auto_ptr&amp;lt;A&amp;gt;(new A(a));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bar(std::auto_ptr&amp;lt;A&amp;gt; pa)&lt;br /&gt;
{&lt;br /&gt;
throw 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
std::auto_ptr&amp;lt;A&amp;gt; pa;&lt;br /&gt;
pa = foo(10); // Здесь все ок - ликов нет&lt;br /&gt;
foo(20); // Здесь тоже все ок, не смотря на то, что возвращаемое значение проигнорировано&lt;br /&gt;
bar(pa); // И здесь все тоже будет хорошо&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Все это делает std::auto_ptr ''особенным объектом'', которые не имеет семантики значения.&lt;br /&gt;
Именно по этому '''его нельзя использовать в контейнерах''' (да и не получится =) ).&lt;br /&gt;
&lt;br /&gt;
==== Особенности ====&lt;br /&gt;
* его нельзя использовать в контейнерах&lt;br /&gt;
* если std::auto_ptr - член класса, то обязятельно '''переопределите конструктор копирования и оператор присваивания или явно запретите их''' (к примеру, при помощи boost::noncopyable)&lt;br /&gt;
* std::auto_ptr не имеет аналогов в boost-е&lt;br /&gt;
* в VS 8.0 реализация std::auto_ptr содержит ошибку.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
std::auto_ptr&amp;lt;int &amp;gt; p;&lt;br /&gt;
p = new int(5); // в этом месте программа упадет.&lt;br /&gt;
// В VS7 такой код не скомпилируется, т.к. отсутствует operator=(T *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
идиома &amp;quot;const std::auto_ptr&amp;quot; - простой способ получить аналог boost::scoped_ptr. const гарантирует, что не произойдет передачи владения.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
std::auto_ptr&amp;lt;T&amp;gt; create_new_T();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
std::auto_ptr&amp;lt;T&amp;gt; const p = create_new_T();&lt;br /&gt;
std::auto_ptr&amp;lt;T&amp;gt; q = p; // это не скомпилируется, благодаря const&lt;br /&gt;
return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== boost::scoped_ptr ===&lt;br /&gt;
Классический умный указатель с безраздельным владением.&lt;br /&gt;
&lt;br /&gt;
==== Особенности ====&lt;br /&gt;
* его нельзя использовать в контейнерах&lt;br /&gt;
* нет метода release&lt;br /&gt;
* нет конструктора копирования и оператора присваивания&lt;br /&gt;
&lt;br /&gt;
=== boost::scoped_array ===&lt;br /&gt;
Аналог boost::scoped_ptr для массивов. Отличается от boost::scoped_ptr тем, что&lt;br /&gt;
удаляет хранимый указатель при помощи '''delete[]'''.&lt;br /&gt;
&lt;br /&gt;
==== Особенности ====&lt;br /&gt;
* его нельзя использовать в контейнерах&lt;br /&gt;
* нет метода release&lt;br /&gt;
* вызывает '''delete[]''' для хранимого указателя&lt;br /&gt;
&lt;br /&gt;
== Умные указатели с раздельным владением ==&lt;br /&gt;
Умные указатели с раздельным владением предназначены для того, что бы разделять один объект&lt;br /&gt;
между несколькими клиентами. Основное отличие указателей этого типа заключается в стратегии&lt;br /&gt;
подсчета ссылок.&lt;br /&gt;
&lt;br /&gt;
=== boost::shared_ptr ===&lt;br /&gt;
Самый мощный и умный указатель. Использует счетчик ссылок в динамической памяти.&lt;br /&gt;
&lt;br /&gt;
==== Особенности ====&lt;br /&gt;
* можно и нужно использовать в контейнерах&lt;br /&gt;
* сохраняет ссылку на функцию delete того модуля, в котором объект был выделен.&lt;br /&gt;
(boost::shared_ptr можно спокойно передать между модулями с разным рантаймом)&lt;br /&gt;
* счетчик ссылок защищен для работы в разных потоках&lt;br /&gt;
(это можно отключить при помощи '''#define BOOST_SP_DISABLE_THREADS''')&lt;br /&gt;
* позволяет хранить указатели разных типов на один объект&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct A {};&lt;br /&gt;
struct B : A {};&lt;br /&gt;
&lt;br /&gt;
boost::shared_ptr&amp;lt;B&amp;gt; pb (new B());&lt;br /&gt;
boost::shared_ptr&amp;lt;A&amp;gt; pa (static_pointer_cast(pb));&lt;br /&gt;
boost::shared_ptr&amp;lt;B&amp;gt; pb2 (dynamic_pointer_cast(pa));&lt;br /&gt;
boost::shared_ptr&amp;lt;const B&amp;gt; pb3 (const_pointer_cast(pa));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== boost::shared_array ===&lt;br /&gt;
Аналог boost::shared_ptr для хранения массивов объектов.&lt;br /&gt;
&lt;br /&gt;
=== boost::intrusive_ptr ===&lt;br /&gt;
Данный умный указатель требует существования двух функций '''intrusive_ptr_add_ref''' и '''intrusive_ptr_add_release''',&lt;br /&gt;
при помощи которых происходит подсчет ссылок. Обычно это означает, что счетчик хранится в самом объекте.&lt;br /&gt;
&lt;br /&gt;
==== Особенности ====&lt;br /&gt;
* можно и нужно использовать в контейнерах&lt;br /&gt;
* требует определения функций '''intrusive_ptr_add_ref''' и '''intrusive_ptr_add_release'''.&lt;br /&gt;
* можно спокойно передать в функцию &amp;quot;чистый&amp;quot; указатель, полученный через '''get()''', а внутри функции снова обернуть его в boost::intrusive_ptr (как часто делается с _com_ptr_t)&lt;br /&gt;
* не существует аналогичного указателя для хранения массивов&lt;br /&gt;
* имеет operator=(T*)&lt;br /&gt;
&lt;br /&gt;
== Умные указатели и boost::bind ==&lt;br /&gt;
Для того, что бы умные указатели работали с boost::bind требуется определить для них функцию&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
T * get_pointer( pointer&amp;lt;T&amp;gt; const&amp;amp; p );&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для большинства умных указателей, которые можно хранить в STL-ных контейнерах,&lt;br /&gt;
эта функция уже определена. &lt;br /&gt;
Для того, что бы заставить работать boost::bind с вашим умным указателем добавить следующий код&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#define BOOST_MEM_FN_ENABLE_STDCALL&lt;br /&gt;
#include &amp;lt;boost/bind.hpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//....&lt;br /&gt;
&lt;br /&gt;
template&amp;lt; class T &amp;gt;&lt;br /&gt;
T * get_pointer( MySmartPtr&amp;lt; T &amp;gt; const&amp;amp; p ) { return p.get(); }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Smal</name></author>	</entry>

	</feed>