如何在 boost 图中对 std::shared_ptr<> 中包装的图属性进行深度复制?

问题描述 投票:0回答:1

我有一个带有自定义属性的增强图。
我想复印一份。我按照以下方法尝试过。

using BGType = boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
                                     // Vertex Properties...
                                     vertexProps,
                                     // Edge Propereties...
                                     edgeProps,
                                     // Graph Properties
                                     graphProps>;

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;
}

struct CustomVertexCopy {
    BGType const &g1;
    BGType &g2;
    void operator()(BGType::vertex_descriptor v1, BGType::vertex_descriptor v2) const
    {
        schVertexProps const &p1 = g1[v1];
        schVertexProps &p2 = g2[v2];
        p2._subGraph = p1._subGraph;
        p2._graph = p1._graph;
        p2._moduleName = p1._moduleName;
        p2._name = p1._name;
    }
};

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; }
};

schGraphProps.h

class schGraphProps {
   public:
    explicit schGraphProps(std::string *name = nullptr) { _name = name ? *name : ""; };

    std::string _name;
    std::map<std::string, std::vector<std::string>> _altNames;
    std::map<std::string, schSymbol> _modSymbol;
    std::shared_ptr<vertexProps> _vertexPtr = nullptr; // ****want to deep copy this property*******
}

一些函数.cpp

OnClick(BGType* bgNew)
{
   // some code
  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);
  // Copying graph properties
  DeepCopyOfBG(bgNew, oldBg);
}


    DeepCopyOfBG(BGType *bGraph, BGType *oldBg)
    {
        boost::copy_graph(
          *bGraph, *oldBg,
          boost::vertex_copy(CustomVertexCopy{*bGraph, *oldBg}).edge_copy(CustomEdgeCopy{*bGraph, *oldBg}));
    
        boost::get_property(*oldBg) = boost::get_property(*bGraph);   

        // Deep copy _altNames map
        for (auto entry : (*bGraph)[boost::graph_bundle]._altNames) {
            std::vector<std::string> deepCopyValues(entry.second.begin(), entry.second.end());
            (*oldBg)[boost::graph_bundle]._altNames[entry.first] = deepCopyValues;

      // Deep copy _modSymbol map
        for (auto entry : (*bGraph)[boost::graph_bundle]._modSymbol) {
            (*oldBg)[boost::graph_bundle]._modSymbol[entry.first] = entry.second;
        }
      
      // Want to copy std::shared_ptr<schVertexProps> _vertexPtr = nullptr

}

我想深度复制以下属性,但无法做到。

std::shared_ptr<vertexProps> _vertexPtr = nullptr

我因为shared_ptr概念而陷入困境。

如何对shared_ptr概念进行深拷贝?

c++ c++11 boost boost-graph
1个回答
0
投票

我的第一反应是:当你想要值语义时,不要使用

shared_ptr

这正是我在之前的回答中向您展示

value_ptr
的原因。这样,零规则就适用,并且语言会自动按照您想要的方式运行。

如果您必须拥有共享指针并且仍然对它们进行深度克隆,则可以复制该

value_ptr
并使其包含一个
shared_ptr
而不是
unique_ptr

如果您不希望这样,或者有其他“自然之力”原因导致您不能(???),您始终可以......只需手动复制对象即可。一般来说,任何唯一指针在概念上的行为都类似于指针。

{
    // clone a pointer
    T* p = new T();
    T* clone = new T(*p);
}
{
    // clone a unique_ptr
    unique_ptr<T> p = std::make_unique<T>();
    unique_ptr<T> clone = std::make_unique<T>(*p);
}
{
    // clone a shared_ptr
    shared_ptr<T> p = std::make_shared<T>();
    shared_ptr<T> clone = std::make_shared<T>(*p);
}

我希望你能发现其中的规律?深度复制基本上只是调用

*p
的复制构造函数:无论
p
指向什么。您拥有哪种(智能)指针甚至并不重要。

{
    // clone a whatever_ptr
    whatever_ptr<T> p = std::make_whatever<T>();
    whatever_ptr<T> clone = std::make_whatever<T>(*p);
}

关于代码,您会遇到更多问题,因为您在同一对象上多次运行

copy_graph
。您还可以运行以下作业两次:

    boost::get_property(*oldBg) = boost::get_property(*bGraph);   

该赋值已复制所有图形属性(

schGraphProps
对象)。

现在,C++ 允许您通过提供用户定义的复制构造函数自定义此类副本的行为。在你的情况下,你可以例如做到:

 schGraphProps(schGraphProps const& other)
     : _name(other._name)
     , _altNames(other._altNames)
     , _modSymbol(other._modSymbol)
     , _vertexPtr(other._vertexPtr ? std::make_shared<vertexProps>(*other._vertexPtr) : nullptr) {}

记住要修复构造函数中的指针误用,正如我之前多次向您展示的那样,您将获得以下类:Live

class schGraphProps {
   public:
     explicit schGraphProps(std::string name = {}) : _name(std::move(name)) {}
     schGraphProps(schGraphProps const& other)
         : _name(other._name)
         , _altNames(other._altNames)
         , _modSymbol(other._modSymbol)
         , _vertexPtr(other._vertexPtr ? std::make_shared<vertexProps>(*other._vertexPtr) : nullptr) {}

     std::string                                     _name;
     std::map<std::string, std::vector<std::string>> _altNames;
     std::map<std::string, schSymbol>                _modSymbol;
     std::shared_ptr<vertexProps>                    _vertexPtr = nullptr;
};

现场演示

我没有心情再次创建完整的演示,因为我不断修复您不断重新引入的错误和不必要的复杂性。所以我将只关注图形属性。

ASIDE 事实上,这可能会帮助您更好地理解 C++ 类型系统的行为。即使作为 BGL 的

adjacency_list
等复杂数据结构的一部分,所有部分仍然“只是 C++ 类型”。如果您使用 C++ 编写代码,那么了解 C++ 类型系统是必须

住在Coliru

#include <cassert>
#include <map>
#include <memory>
#include <string>
#include <vector>

struct vertexProps{};
struct schSymbol{};

class schGraphProps {
   public:
     explicit schGraphProps(std::string name = {}) : _name(std::move(name)) {}
     schGraphProps(schGraphProps const& other)
         : _name(other._name)
         , _altNames(other._altNames)
         , _modSymbol(other._modSymbol)
         , _vertexPtr(other._vertexPtr ? std::make_shared<vertexProps>(*other._vertexPtr) : nullptr) {}

     std::string                                     _name;
     std::map<std::string, std::vector<std::string>> _altNames;
     std::map<std::string, schSymbol>                _modSymbol;
     std::shared_ptr<vertexProps>                    _vertexPtr = nullptr;
};

#include <iostream>
int main() {
    auto v = std::make_shared<vertexProps>();

    schGraphProps graphProps1{"hello"};
    graphProps1._vertexPtr = v;

    // clone it!
    auto graphProps2 = graphProps1; // uses copy constructor

    std::cout << "Original v:\t" << v.get() << "\n";
    std::cout << "graphProps1._vertexPtr:\t" << graphProps1._vertexPtr.get() << "\n";
    std::cout << "graphProps2._vertexPtr:\t" << graphProps2._vertexPtr.get() << "\n";
    assert(graphProps1._vertexPtr == v);
    assert(graphProps2._vertexPtr != v); // deep copied
}

打印例如

Original v: 0xbce030
graphProps1._vertexPtr: 0xbce030
graphProps2._vertexPtr: 0xbce050

所有断言都通过,证明了深拷贝。

© www.soinside.com 2019 - 2024. All rights reserved.