BOOST_FOREACH Итерация над boost::shared_ptr<список>
Я делаю что-то похожее на этот пункт Правильное использование BOOST_FOREACH?
Тем не менее, мой возвращенный список обернут в boost::shared_ptr. Если я не назначу список переменной до цикла BOOST_FOREACH, я получаю сбой во время выполнения, поскольку список разрушается, поскольку он временный.
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;
}
Тогда позже..
// 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;
}
Я хотел бы иметь возможность использовать вышесказанное, не вводя переменную "myList". Это возможно?
2 ответа
Хорошо, "Лучшая практика" для shared_ptr упоминает, что следует избегать использования неназванных временных:
http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm
Избегайте использования безымянных временных переменных shared_ptr для сохранения набора текста; чтобы понять, почему это опасно, рассмотрим пример:
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()); }
Функция ok следует указаниям на букву, тогда как bad создает временный shared_ptr, допуская возможность утечки памяти. Поскольку аргументы функции вычисляются в неуказанном порядке, возможно, что новый int(2) будет оцениваться первым, g() вторым, и мы никогда не сможем добраться до конструктора shared_ptr, если g выдает исключение.
Описанная выше проблема безопасности исключений также может быть устранена с помощью фабричных функций make_shared или allocate_shared, определенных в boost/make_shared.hpp. Эти заводские функции также обеспечивают повышение эффективности за счет консолидации распределений.
Вам необходимо использовать:
T* boost::shared_ptr<T>::get()
Пример:
BOOST_FOREACH( int i, static_cast< list<int> >( *(GetList().get()) ) ) {
}
Проблема в том, что вы не можете разыменовать boost:: shared_ptr и надеяться, что он возвращает базовый объект, который он хранит. Если бы это было правдой, то не было бы никакого способа разыменовать указатель на boost:: shared_ptr. Вам нужно использовать специализированный метод::get(), чтобы вернуть объект, сохраненный в boost:: shared_ptr, и затем разыменовать его.
См. http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/shared_ptr.htm для документации.