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 开发者_Go百科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?
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.
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 can't dereference a boost::shared_ptr and hope it returns the underlying object it stores. If this was true, then there would be no way to dereference a pointer to a boost::shared_ptr. You need to use the specialized ::get() method to return the object stored by boost::shared_ptr, and then dereference that.
See http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/shared_ptr.htm#get for the documentation.
精彩评论