【问题标题】:BOOST_FOREACH Iteration over boost::shared_ptr<list>BOOST_FOREACH 迭代 boost::shared_ptr<list>
【发布时间】:2011-07-04 15:45:04
【问题描述】:

我正在做类似这个项目Correct BOOST_FOREACH usage?

但是,我返回的列表包含在 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”。 这可能吗?

【问题讨论】:

  • 它是如何崩溃的?有任何断言失败吗?还是别的什么?
  • BOOSTFOREACH.exe 中 0x00426692 处未处理的异常:0xC0000005:访问冲突读取位置 0xfeeefeee。
  • 我假设崩溃是因为 list 已被销毁(我通过析构函数进行了跟踪),但 BOOST_FOREACH 在尝试调用 list::begin() 时出错跨度>
  • 您正在取消对 shared_ptr 的引用,但从未将其复制到新的 shared_ptr 中,因此引用计数将达到 0 并且将被销毁。如果您要尝试执行 auto list = GetList();在 BOOST_FOREACH( int i, *list ) 之前的行上,它应该修复该特定错误。
  • 是的,看起来这是我最终需要做的事情。我开始使用 BOOST_FOREACH 来避免一开始就必须这样做。

标签: c++ boost shared-ptr temporaries boost-foreach


【解决方案1】:

好的,shared_ptr 的“最佳实践”提到避免使用未命名的临时对象:

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

避免使用未命名的 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 遵循指南 信,而坏的结构 临时的 shared_ptr 到位, 承认记忆的可能性 泄漏。由于函数参数是 以未指定的顺序评估,它是 new int(2) 可能是 首先评估,g() 第二,然后我们 可能永远无法到达 shared_ptr 如果 g 抛出异常,则构造函数。

上述异常安全问题也可以通过使用 boost/make_shared.hpp 中定义的 make_shared 或 allocate_shared 工厂函数来消除。这些工厂功能还通过整合分配提供了效率优势。

【讨论】:

    【解决方案2】:

    你需要使用:

    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#get

    【讨论】:

    • “如果这是真的,那么就没有办法取消引用指向 boost::shared_ptr 的指针。”这听起来不对。这两个断言之间没有逻辑联系,实际上至少部分错误:Dereferencing a shared_ptr does return the underlying object
    • 我不再遇到您上面建议的行的崩溃。出于好奇,我也尝试了 BOOST_FOREACH(int i, static_cast >(*GetList()) ),但效果很好,但我不清楚为什么。
    • 如果我猜是 static_cast 强制复制列表,而只有 *GetList 使用对现已销毁列表的引用(因为 shared_ptr 已销毁)。
    • 也许它的废话隐藏在导致问题的 FOR_EACH 宏中。
    • static_cast 确实导致调用列表复制ctor,我试图通过传递智能指针而不是列表副本来避免这种情况发生
    猜你喜欢
    • 1970-01-01
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多