我正在使用CUDD包进行BDD操作。 我想在其中制作一个名为DdManager的大数据结构的副本。 问题是:这个数据结构里面有很多指针,所以当我进行直接复制时,它是一个“浅”副本(因为有些人使用这个术语)即:新副本中的指针指向同一个地方指向通过原始副本,所以当我改变其中任何一个时,我也会改变另一个不受欢迎的...... 试图手工制作复制功能是不可行的,因为数据结构非常大且非常详细,许多指针也指向其他复杂结构! 我已经尝试了here描述的向量解决方案但是我没有得到预期的结果,因为有许多嵌套结构和指针,我想要一个全新的副本。
以下是我想要做的代码示例:
#include <iostream>
#include <cstdlib>
#include <string.h>
#include <vector>
using namespace std;
struct n1
{
int a;
char *b;
};
struct n2
{
int **c;
struct n1 *xyz;
};
typedef struct
{
vector<struct n2> x;
}X;
int main()
{
struct n2 s1;
s1.xyz = (struct n1*)malloc(sizeof(struct n1));
s1.xyz->a = 3;
s1.xyz->b = (char*)malloc(5);
s1.xyz->b[0] = '\0';
strcat(s1.xyz->b,"Mina");
s1.c = (int**)malloc(5 * sizeof(int*));
for(int i = 0; i < 5; i++)
s1.c[i] = (int*)malloc(5 * sizeof(int));
for(int i = 0; i < 5; i++)
for(int j = 0 ; j < 5 ; j++)
s1.c[i][j] = i + j;
X struct1,struct2;
vector<struct n2>::iterator it;
it = struct1.x.begin();
it = struct1.x.insert(it,s1);
it = struct2.x.begin();
it = struct2.x.insert(it,struct1.x[0]);
cout<<"struct2.x[0].c[1][2] = "<<struct2.x[0].c[1][2] <<" !"<<endl; // This is equal to 3
(struct2.x[0].c[1][2])++; //Now it becomes 4
cout<<"struct2.x[0].c[1][2] = "<<struct2.x[0].c[2][2] <<" !"<<endl; //This will print 4
cout<<"s1.c[1][2] "<< s1.c[1][2]<<" !"<<endl; // This will also print 4 ... that's the wrong thing
return 0;
}
答案 0 :(得分:3)
尽管有人说你必须
手动制作复制功能
......为了解决这个问题,我认为这对你来说是错误的。这就是原因,这是一个建议。
您正在尝试创建CUDD ddManager对象的副本,该对象是复杂CUDD库的组成部分。 CUDD在内部使用某些对象的引用计数(这可能对您有所帮助......)但是ddManager对象实际上代表了库的整个实例,而且我不知道引用计数如何跨实例工作。
CUDD库及其associated C++ wrapper似乎没有提供必要的拷贝构造函数来创建ddManager的单独副本,并且添加这些可能需要认真的努力,以及对您的库的详细内部知识只是想用作客户端。尽管可以做到这一点,但这样做很复杂。
相反,我会尝试将当前的BDD写入文件/流/其他内容,然后将其读回到ddManager的新实例中。有一个名为dddmp的库可以帮助你解决这个问题。
我还建议修改C ++包装器以生成ddManager类non-copyable。
答案 1 :(得分:1)
“尝试手工制作复制功能是不可行的,因为数据结构非常大且非常详细,并且还有许多指向其他复杂结构的指针!!!”
这正是你必须要做的。 客观方法意味着您不会编写一个大的do-it-all复制方法。相反,每个对象(结构)只复制自身,然后调用它的子对象复制方法等,直到没有其他东西可以复制。
没有“矢量解决方案”这样的东西,矢量就是它最小的复制方法的最小对象。
struct和class之间没有区别,所以只需编写它们的复制方法。
只有您了解数据的结构,因此您是唯一可以拯救人类(或复制此数据)的人。