c++boostshared-ptrtemporariesboost-foreach

BOOST_FOREACH Iteration over boost::shared_ptr<list>


I'm doing something similar to this item Correct BOOST_FOREACH usage?

However, my returned list is wrapped in a boost::shared_ptr. If I do not assign the list to a variable before the BOOST_FOREACH loop, I get a crash at runtime as the list is getting destructed as it is a 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 having to introduce a variable 'myList'. Is this possible?


Solution

  • Ok, the 'Best Practice' for shared_ptr mentions to avoid using unnamed temporaries:

    http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm#BestPractices

    Avoid using unnamed shared_ptr temporaries to save typing; to see why this is dangerous, consider this 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 function ok follows the guideline to the letter, whereas bad constructs the temporary shared_ptr in place, admitting the possibility of a memory leak. Since function arguments are evaluated in unspecified order, it is possible for new int(2) to be evaluated first, g() second, and we may never get to the shared_ptr constructor if g throws an exception.

    The exception safety problem described above may also be eliminated by using the make_shared or allocate_shared factory functions defined in boost/make_shared.hpp. These factory functions also provide an efficiency benefit by consolidating allocations.