我有一个带有自定义属性的增强图。
我想复印一份。我按照以下方法尝试过。
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概念进行深拷贝?
我的第一反应是:当你想要值语义时,不要使用
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 的
等复杂数据结构的一部分,所有部分仍然“只是 C++ 类型”。如果您使用 C++ 编写代码,那么了解 C++ 类型系统是必须。adjacency_list
#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
所有断言都通过,证明了深拷贝。