TITLE: what is auto_ptr_ref for? (Newsgroups: comp.lang.c++.moderated, 9 Feb 2000) POLK: Max Polk >I'm at a loss to understand the syntax of auto_ptr_ref in the C++ >standard. It states in 20.4.5.2 that auto_ptr_ref holds a reference to >an auto_ptr, and that it has use during auto_ptr conversion when an >auto_ptr is passed to or returned from functions. NARAN: sbnaran@uiuc.edu (Siemel B. Naran) The conversion from auto_ptr to auto_ptr_ref along with the constructor to construct an auto_ptr from an auto_ptr_ref supply the auto_ptr class with a second copy constructor, effectively auto_ptr::auto_ptr(const auto_ptr&); Consider this setup auto_ptr function(); int main() { auto_ptr f=function(); } Notice that the return value of 'function()' is a temporary (ie, an unnamed variable that will be destroyed automatically at the end of the expression). The rules of C++ forbid the compiler from using auto_ptr::auto_ptr(auto_ptr&) to copy this return value into the local variable 'f'. In C++, all temporaries must be passed by const reference or by value; this is to keep programmers from making changes to an object that is going to be destroyed anyway -- likely a design error. (However, you can call non-const member functions on a temporary, see below.) So how does the compiler create 'f' from the return value of 'function()'? The answer has to do with the nested auto_ptr_ref class. The compiler employs a two-step process. First, convert the auto_ptr to an auto_ptr_ref, whereupon the auto_ptr gives up ownership of the pointed-to object. (Notice that we are calling a non-const member function, namely the operator conversion, on a temporary.) Second, convert the auto_ptr_ref to an auto_ptr. This latter auto_ptr is just 'f1', and it now assumes ownership of the pointed-to object. My thanks to Dietmar Kuel for pointing this out to me some months ago on this newsgroup. Also observe that auto_ptr_ref is useful for returning temporary auto_ptr objects, as in function2() below. Try this program: #include class auto_ptr { private: struct auto_ptr_ref { }; public: auto_ptr() { cout << "auto_ptr::auto_ptr()\n"; } auto_ptr(auto_ptr&) { cout << "auto_ptr::auto_ptr(auto_ptr&)\n"; } operator auto_ptr_ref() { cout << "auto_ptr::operator auto_ptr_ref()\n"; } auto_ptr(auto_ptr_ref) { cout << "auto_ptr::auto_ptr(auto_ptr_ref)\n"; } ~auto_ptr() { cout << "auto_ptr::~auto_ptr()\n"; } }; auto_ptr function1(); auto_ptr function2(); int main() { auto_ptr f1=function1(); // calls function function1(), see below now // looks for "auto_ptr::auto_ptr(const auto_ptr&)", not found // can't use "auto_ptr::auto_ptr(auto_ptr&)" // because return value of 'function1()' is a temporary // so consider two-step routes now // 1) use "auto_ptr::operator auto_ptr_ref()" // 2) use "auto_ptr::auto_ptr(auto_ptr_ref)" to construct 'f1' // call to "auto_ptr::~auto_ptr()" to destroy return of 'function1()' cout << "after1\n"; auto_ptr f2=function2(); // figure this one out yourself cout << "after2\n"; } // 2 calls to "auto_ptr::~auto_ptr()" to destroy 'f1' and 'f2' auto_ptr function1() // comments assume no return value optimization { auto_ptr a; // call to "auto_ptr::auto_ptr()" return a; // call to "auto_ptr::auto_ptr(auto_ptr&)" } // call to "auto_ptr::~auto_ptr()" to destroy 'a' auto_ptr function2() // figure this one out yourself, uses auto_ptr_ref { return auto_ptr(); } _______________________________________________ cpptips mailing list http://cpptips.hyperformix.com