You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用member_hook的Boost.Intrusive push_back为何与原对象地址不匹配?

为何使用list_member_hook<>的Boost Intrusive链表断言会失败?

以下是出现问题的代码:

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

using namespace boost::intrusive;
class A
{
public:
    int i_;
    A(int i) : i_(i) {};

    list_member_hook<> m_hook1;
};

typedef list<A, member_hook<A, list_member_hook<>, &A::m_hook1> > List1;

int main()
{
    List1 list1;
    A *a = new A(10);

    list1.push_back(*a);
    assert( a == &list1.back()); // 断言失败,原因是什么?

     return 0;
}

问题描述:将动态分配的对象a通过push_back加入链表list1后,断言a与&list1.back()相等失败,请问原因是什么?


原因分析

问题出在list_member_hook<>的默认链接模式上:它默认使用link_mode<auto_unlink>。这种模式为了实现对象析构时自动从链表解绑的功能,会修改hook内部的指针值。

Boost Intrusive链表的元素访问依赖于从hook地址反向计算所属对象的地址。当auto_unlink模式修改了hook的指针后,这个反向计算逻辑会出错,导致list1.back()返回的对象地址和原指针a不匹配,断言因此失败。

解决方法

修改list_member_hook的模板参数,指定不修改hook指针的链接模式即可,比如safe_link或normal_link:

class A
{
public:
    int i_;
    A(int i) : i_(i) {};

    // 使用safe_link模式,支持安全的自动解绑且不破坏地址计算
    list_member_hook<link_mode<safe_link>> m_hook1;
};

或者选择normal_link模式(无自动解绑,需手动管理对象在链表中的生命周期):

list_member_hook<link_mode<normal_link>> m_hook1;

修改后,hook内部指针不会被修改,通过list1.back()获取的对象地址会和原指针a完全一致,断言即可通过。


内容的提问来源于stack exchange,提问作者Alex Net

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 23:11:04