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 для документации.

Другие вопросы по тегам