【问题标题】:Why boost intrusive list 's push_back function requires lvalue?为什么 boost intrusive list 的 push_back 函数需要左值?
【发布时间】:2019-09-23 15:11:19
【问题描述】:

我正在学习侵入式列表:

#include <iostream>
#include <list>
#include <boost/intrusive/list.hpp>


struct DummyObject : public boost::intrusive::list_base_hook<>{
  double price;

  DummyObject(const double a): price(a){

  }
};

using IntrusiveListContainer = boost::intrusive::list<DummyObject>;
using NonintrusiveListContainer = std::list<DummyObject>;

int main()
{

  IntrusiveListContainer  intrusivecontainer;
  NonintrusiveListContainer  nonintrusivecontainer;

  intrusivecontainer.push_back(DummyObject (22.2)); // ERROR
  nonintrusivecontainer.push_back(DummyObject (22.2));// compiled

  return 0;
}

我了解侵入式列表的基本概念,但我不明白为什么 push_back 需要专门的左值。从逻辑的角度来看,为什么侵入式列表无法处理 rvalue ?

左值要求是否意味着用户需要自己处理 DummyObject 的生命周期?也就是说,当 IntrusiveList pop_front 时,弹出的对象不会被破坏?

另外,我通过左值传递的事件:

int main()
{

  IntrusiveListContainer  intrusivecontainer;
  NonintrusiveListContainer  nonintrusivecontainer;
  DummyObject a(22.2);
  intrusivecontainer.push_front(a); // compiled
  //nonintrusivecontainer.push_back(DummyObject (22.2));// compiled

  return 0;
}

二进制文件中的一个断言失败:

intrusivelist: /usr/include/boost/intrusive/detail/generic_hook.hpp:48: void boost::intrusive::detail::destructor_impl(Hook&, boost::intrusive::detail::link_dispatch) [with Hook = boost::intrusive::generic_hook]: 断言 `!hook.is_linked()' 失败。

【问题讨论】:

    标签: c++ rvalue lvalue intrusive-containers boost-intrusive


    【解决方案1】:

    这是一个简单的侵入式容器,不执行内存管理。您有责任确保存储的对象比侵入式容器的寿命更长。

    这是在文档中指出的:

    Intrusive and non-intrusive containers - 1.64.0

    • 用户必须独立于容器管理插入对象的生命周期

    现在临时对象的寿命会比侵入式容器更短,从而导致未定义的行为,侵入式容器不会创建任何副本。所以不需要使用 r 值。

    现在这个版本的示例 works fine(没有崩溃):

    int main()
    {
      DummyObject a(22.2);
      IntrusiveListContainer  intrusivecontainer;
      NonintrusiveListContainer  nonintrusivecontainer;
    
      intrusivecontainer.push_back(a); // ERROR
      nonintrusivecontainer.push_back(a);// compiled
    
      return 0;
    }
    

    另一方面,这个版本ends with assertion failure

    int main()
    {
      IntrusiveListContainer  intrusivecontainer;
      NonintrusiveListContainer  nonintrusivecontainer;
      DummyObject a(22.2);
    
      intrusivecontainer.push_back(a); // ERROR
      nonintrusivecontainer.push_back(a);// compiled
    
      return 0;
    }
    

    【讨论】:

    • 我想在我的项目中使用侵入式列表,因为我需要 1. 在不同的容器中拥有一个对象; 2.旅行列表时缓存丢失更少。如果我想实现这些目标,我应该使用带有对象池的侵入式列表吗?这是侵入式列表的常见用例吗?
    • 是的,这对于侵入式容器来说是一个很好的用例。只需阅读有关侵入式容器的优缺点的文档(还有关于非侵入式容器的优缺点的部分),它涵盖了您列出的所有内容。
    猜你喜欢
    • 1970-01-01
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2021-09-30
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多