BOOST_FOREACH Iterate over boost :: shared_ptr <list>
I am doing something similar to this element. Fixed the use of BOOST_FOREACH?
However, my returned list is wrapped in boost :: shared_ptr. If I do not assign the list to a variable before the BOOST_FOREACH loop, I get a crash at runtime because the list is being destroyed because it is temporary.
boost::shared_ptr< list<int> > GetList() { boost::shared_ptr< list<int> > myList( new list<int>() ); myList->push_back( 3 ); myList->push_back( 4 ); return myList; } Then later ..
// Works if I comment out the next line and iterate over myList instead // boost::shared_ptr< list<int> > myList = GetList(); BOOST_FOREACH( int i, *GetList() ) // Otherwise crashes here { cout << i << endl; } I would like to be able to use the above without introducing the myList variable. Is it possible?
Well, the "Best Practice" for shared_ptr mentions to avoid using unnamed temporary files:
http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm#BestPractices
Avoid using unnamed shared_ptr temporary files to save input; see why it is dangerous, think about it Example:
void f(shared_ptr<int>, int); int g(); void ok() { shared_ptr<int> p(new int(2)); f(p, g()); } void bad() { f(shared_ptr<int>(new int(2)), g()); } The ok function corresponds to the manual for the letter, while the poor constructions are temporary shared_ptr in place, allowing the memory to leak. Since function arguments are evaluated in an unspecified order, it is possible for a new int (2) to be evaluated first by g (), and we may never get into the shared_ptr constructor if g throws an exception.
The exception safety issue described above can also be fixed using the make_shared or allocate_shared factory functions defined in boost / make_shared.hpp. These factory functions also provide efficiency in consolidating distributions.
You need to use:
T* boost::shared_ptr<T>::get() Example:
BOOST_FOREACH( int i, static_cast< list<int> >( *(GetList().get()) ) ) { } The problem is that you cannot cast boost :: shared_ptr and hope that it returns the underlying object that it stores. If that were true, then there would be no way to dereference a pointer to boost :: shared_ptr. You need to use the special :: get () method to return the object saved by boost :: shared_ptr, and then dereference it.
See http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/shared_ptr.htm#get for documentation.