| <section xmlns="http://docbook.org/ns/docbook" version="5.0" | |
| xml:id="std.util.memory.auto_ptr" xreflabel="auto_ptr"> | |
| <?dbhtml filename="auto_ptr.html"?> | |
| <info><title>auto_ptr</title> | |
| <keywordset> | |
| <keyword>ISO C++</keyword> | |
| <keyword>auto_ptr</keyword> | |
| </keywordset> | |
| </info> | |
| <section xml:id="auto_ptr.limitations"><info><title>Limitations</title></info> | |
| <para>Explaining all of the fun and delicious things that can | |
| happen with misuse of the <classname>auto_ptr</classname> class | |
| template (called <acronym>AP</acronym> here) would take some | |
| time. Suffice it to say that the use of <acronym>AP</acronym> | |
| safely in the presence of copying has some subtleties. | |
| </para> | |
| <para> | |
| The AP class is a really | |
| nifty idea for a smart pointer, but it is one of the dumbest of | |
| all the smart pointers -- and that's fine. | |
| </para> | |
| <para> | |
| AP is not meant to be a supersmart solution to all resource | |
| leaks everywhere. Neither is it meant to be an effective form | |
| of garbage collection (although it can help, a little bit). | |
| And it can <emphasis>not</emphasis>be used for arrays! | |
| </para> | |
| <para> | |
| <acronym>AP</acronym> is meant to prevent nasty leaks in the | |
| presence of exceptions. That's <emphasis>all</emphasis>. This | |
| code is AP-friendly: | |
| </para> | |
| <programlisting> | |
| // Not a recommend naming scheme, but good for web-based FAQs. | |
| typedef std::auto_ptr<MyClass> APMC; | |
| extern function_taking_MyClass_pointer (MyClass*); | |
| extern some_throwable_function (); | |
| void func (int data) | |
| { | |
| APMC ap (new MyClass(data)); | |
| some_throwable_function(); // this will throw an exception | |
| function_taking_MyClass_pointer (ap.get()); | |
| } | |
| </programlisting> | |
| <para>When an exception gets thrown, the instance of MyClass that's | |
| been created on the heap will be <function>delete</function>'d as the stack is | |
| unwound past <function>func()</function>. | |
| </para> | |
| <para>Changing that code as follows is not <acronym>AP</acronym>-friendly: | |
| </para> | |
| <programlisting> | |
| APMC ap (new MyClass[22]); | |
| </programlisting> | |
| <para>You will get the same problems as you would without the use | |
| of <acronym>AP</acronym>: | |
| </para> | |
| <programlisting> | |
| char* array = new char[10]; // array new... | |
| ... | |
| delete array; // ...but single-object delete | |
| </programlisting> | |
| <para> | |
| AP cannot tell whether the pointer you've passed at creation points | |
| to one or many things. If it points to many things, you are about | |
| to die. AP is trivial to write, however, so you could write your | |
| own <code>auto_array_ptr</code> for that situation (in fact, this has | |
| been done many times; check the mailing lists, Usenet, Boost, etc). | |
| </para> | |
| </section> | |
| <section xml:id="auto_ptr.using"><info><title>Use in Containers</title></info> | |
| <para> | |
| </para> | |
| <para>All of the <link linkend="std.containers">containers</link> | |
| described in the standard library require their contained types | |
| to have, among other things, a copy constructor like this: | |
| </para> | |
| <programlisting> | |
| struct My_Type | |
| { | |
| My_Type (My_Type const&); | |
| }; | |
| </programlisting> | |
| <para> | |
| Note the const keyword; the object being copied shouldn't change. | |
| The template class <code>auto_ptr</code> (called AP here) does not | |
| meet this requirement. Creating a new AP by copying an existing | |
| one transfers ownership of the pointed-to object, which means that | |
| the AP being copied must change, which in turn means that the | |
| copy ctors of AP do not take const objects. | |
| </para> | |
| <para> | |
| The resulting rule is simple: <emphasis>Never ever use a | |
| container of auto_ptr objects</emphasis>. The standard says that | |
| <quote>undefined</quote> behavior is the result, but it is | |
| guaranteed to be messy. | |
| </para> | |
| <para> | |
| To prevent you from doing this to yourself, the | |
| <link linkend="manual.ext.compile_checks">concept checks</link> built | |
| in to this implementation will issue an error if you try to | |
| compile code like this: | |
| </para> | |
| <programlisting> | |
| #include <vector> | |
| #include <memory> | |
| void f() | |
| { | |
| std::vector< std::auto_ptr<int> > vec_ap_int; | |
| } | |
| </programlisting> | |
| <para> | |
| Should you try this with the checks enabled, you will see an error. | |
| </para> | |
| </section> | |
| </section> |