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

如何深度拷贝包含子图的Boost图顶点属性?

问题描述

我有一个带自定义属性的Boost图,目前通过自定义拷贝结构体实现了部分属性拷贝,但顶点属性里的BGType* _subGraph字段只是浅拷贝,导致新图和旧图共享子图实例。需要实现这个字段的深度拷贝,该怎么处理?


相关代码

BGType 类型定义

using BGType = boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
                                     // 顶点属性
                                     vertexProps,
                                     // 边属性
                                     edgeProps,
                                     // 图属性
                                     graphProps>;

vertexProps 类定义(vertexProps.h)

class vertexProps {
public:
    explicit vertexProps(const std::string *moduleName = nullptr, const std::string *name = nullptr,
                        long refPtr = 0 )
     : _refPtr(refPtr)
    {
        _moduleName = moduleName ? *moduleName : "";
        _name = name ? *name : "";
    };
    std::string _moduleName;
    std::string _name;
    BGType *_subGraph = nullptr;
    BGType *_graph = nullptr;
    long _refPtr; // 补充原代码遗漏的成员
};

自定义顶点拷贝结构体

struct CustomVertexCopy {
    BGType const &g1;
    BGType &g2;
    void operator()(BGType::vertex_descriptor v1, BGType::vertex_descriptor v2) const
    {
        vertexProps const &p1 = g1[v1];
        vertexProps &p2 = g2[v2];
        p2._subGraph = p1._subGraph; // 此处为浅拷贝,需修改
        p2._graph = p1._graph;
        p2._moduleName = p1._moduleName;
        p2._name = p1._name;
        p2._refPtr = p1._refPtr;
    }
};

edgeProps 类与自定义边拷贝结构体(edgeProps.h)

class edgeProps {
public:
    explicit edgeProps(std::string name = "")
        : _name(name){};
    std::string _name;
};

struct CustomEdgeCopy {
    BGType const &g1;
    BGType &g2;

    void operator()(BGType::edge_descriptor e1, BGType::edge_descriptor e2) const { 
        g2[e2]._name = g1[e1]._name; 
    }
};

拷贝调用代码(someFunction.cpp)

void OnClick(BGType* bgNew)
{
   // 其他业务代码
  BGType* oldBg = new BGType;
  boost::copy_graph(
                  *bgNew, *oldBg,
                  boost::vertex_copy(CustomVertexCopy{*bgNew, *oldBg}).edge_copy(CustomEdgeCopy{*bgNew, *oldBg}));
  boost::get_property(*oldBg) = boost::get_property(*bgNew);
  // 拷贝图属性
  DeepCopyOfBG(bgNew, oldBg);
}

图属性深拷贝函数

void someFunction::DeepCopyOfBG(BGType* bGraph, BGType* oldBg)
{
    // 遍历源图的_modInfo并拷贝内容
    for (const auto& entry : (*bGraph)[boost::graph_bundle]._modInfo) {
        const std::string& key = entry.first;
        const auto& value = entry.second;

        // 创建value的深拷贝(包含schPinInfo*向量的元组)
        std::tuple<std::vector<schPinInfo*>, std::vector<schPinInfo*>, std::vector<schPinInfo*>> deepCopyValue = value;

        // 将深拷贝添加到目标图的_modInfo中
        (*oldBg)[boost::graph_bundle]._modInfo[key] = deepCopyValue;
    }
    // 其他属性拷贝逻辑
}

解决方法

要实现_subGraph的深度拷贝,需在自定义顶点拷贝逻辑中递归创建并拷贝子图实例,同时修正_graph指针指向新的图实例。

1. 修改CustomVertexCopy结构体

更新顶点拷贝逻辑,对_subGraph进行递归深拷贝,同时修正_graph指针指向新图:

struct CustomVertexCopy {
    BGType const &g1;
    BGType &g2;
    void operator()(BGType::vertex_descriptor v1, BGType::vertex_descriptor v2) const
    {
        vertexProps const &p1 = g1[v1];
        vertexProps &p2 = g2[v2];

        // 拷贝基础属性
        p2._moduleName = p1._moduleName;
        p2._name = p1._name;
        p2._refPtr = p1._refPtr;

        // 修正_graph指针:新顶点的_graph指向当前拷贝的新图
        p2._graph = &g2;

        // 深度拷贝_subGraph
        if (p1._subGraph != nullptr) {
            // 创建新的子图实例
            p2._subGraph = new BGType;
            // 递归调用copy_graph,复用自定义拷贝逻辑处理子图的顶点和边
            boost::copy_graph(
                *p1._subGraph, 
                *p2._subGraph,
                boost::vertex_copy(CustomVertexCopy{*p1._subGraph, *p2._subGraph})
                .edge_copy(CustomEdgeCopy{*p1._subGraph, *p2._subGraph})
            );
            // 拷贝子图的图属性
            boost::get_property(*p2._subGraph) = boost::get_property(*p1._subGraph);
            // 调用DeepCopyOfBG处理子图的额外自定义属性
            DeepCopyOfBG(p1._subGraph, p2._subGraph);
        } else {
            p2._subGraph = nullptr;
        }
    }
};

2. 补充内存管理逻辑

为避免内存泄漏,给vertexProps添加析构函数释放_subGraph资源:

class vertexProps {
    // ... 现有成员 ...
    ~vertexProps() {
        delete _subGraph; // 递归释放子图,子图的顶点会触发自身析构
    }
};

注意:如果存在循环引用(比如子图顶点的_graph指向父图),需改用std::shared_ptr<BGType>代替裸指针,否则会导致析构时无限递归或内存泄漏。

3. 调整图属性拷贝逻辑

如果图属性中也存在指向自身的指针,需在DeepCopyOfBG中同步修正,确保新图的属性指向自身而非原实例。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 03:24:52