通常のアプローチは、古いポインタから新しいポインタへのある種のマッピング フォームを保持することです。コピーを作成する前に、マップを参照して、オブジェクトが既にコピーされているかどうかを確認し、コピーされている場合は既存のコピーを返し、そうでない場合は clone() を呼び出します。
このようなもの:
#include <unordered_map>
#include <vector>
typedef std::unordered_map<void *, void *> map_type;
template<typename T>
T *clone (T *ptr, map_type &m)
{
auto p = m.find (ptr);
if (p != m.end ())
return static_cast<T *> (p->second);
else
return ptr->clone (m);
}
struct S
{
int x;
std::vector<S *> v;
S *clone (map_type &m)
{
S *p = new S;
// this is important to happen before calling clone() on subobjects
m [this] = p;
p->x = x;
for (auto q: v)
p->v.push_back (::clone (q, m));
return p;
}
};
int
main ()
{
S *p = new S ();
p->x = 1;
S *q = new S ();
q->x = 2;
S *r = new S ();
r->x = 3;
p->v.push_back (p);
p->v.push_back (p);
p->v.push_back (q);
q->v.push_back (p);
q->v.push_back (r);
r->v.push_back (p);
map_type m;
S *x;
x = clone (p, m);
}