我正在尝试对对象进行深层复制(用于写入时的复制),但是我遇到了分段错误。
我正在使用带链表的哈希表。
class Person
{
public:
Person(const char * id,int nb)
{
this->id=strdup(id);
this->nb=nb;
this->init=init;
this->next=NULL;
}
Person(const Person& rhs) :
nb(rhs.nb),
init(rhs.init),
id(strdup(rhs.id)),
next(rhs.next == NULL ? NULL : new Person(*rhs.next)) {}
char* strdup(char const* in)
{
char* ret = new char[strlen(in)+1];
strcpy(ret, in);
return ret;
}
int nb,init;
const char * id;
Person *next;
};
Hashtable deepcopy (const Hashtable& rhs)
{
num[0]=num[0]-1;
Person** array=rhs.table;
Hashtable autre;
for (int i = 0 ; i < size; ++i)
if (autre.table[i]!=NULL)
autre.table[i] = new Person(*array[i]);
return autre;
num[0]=1;
}
我班Hashtable的归属:
Person **table;
int* num;
编辑:此问题似乎已修复。 我的深拷贝有什么问题?我不明白。我认为我的拷贝构造函数很好,但我不明白为什么在运行它时会出现seg错误。
答案 0 :(得分:1)
此代码必须修复:
for (int i = 0 ; i < size; ++i)
autre.table[i] = new Person(*array[i]);
table
具有固定大小,并且填充了空指针。在循环中,您不检查要复制的元素是否为空指针,因此您要对其进行反驳并尝试复制甚至不存在的实体。
for (int i = 0 ; i < size; ++i) {
if(array[i] != NULL) {
autre.table[i] = new Person(*array[i]);
}
}
PS:最好使用nullptr
代替NULL
。
答案 1 :(得分:0)
我看到的问题:
Person
的默认构造函数。
Person(const char * id,int nb)
{
this->id=id;
this->next=NULL;
}
如果我使用
Person foo()
{
char id[] = "John";
return Person(id, 0);
}
Person a = foo();
然后堆栈存储器用于保存&#34; John&#34; foo
中的a
现在由std::string
保留,这将导致未定义的行为。
您需要获取输入字符串的所有权。使用id
代替char const*
。
复制Person
的构造函数。
声明
id(rhs.id),
如果您决定将char const*
用作id
的类型,将会出现问题。如果您将其切换为std::string
,则不会出现问题。
HashTable
的复制构造函数生成table
的浅表副本。如果您决定删除table
的析构函数中的HashTable
,这将是一个问题。如果您未在table
的析构函数中删除HashTable
,则会导致内存泄漏。
在deepcopy
中,在解除引用之前,您不会检查array[i]
是否为NULL。 @alphashooter已经指出了这一点。此外,您正在函数autre
的局部变量中创建深层副本。除非您从中返回autre
,否则深层副本在函数外部不可见。
修改强>
由于您不允许使用std::string
,因此您必须为默认构造函数中的char const*
以及复制构造函数分配内存。如果您的平台具有非标准函数strdup
并且您可以使用它,则可以将默认构造函数更改为:
Person(const char * id,int nb)
{
this->id=strdup(id);
this->next=NULL;
}
您需要对复制构造函数进行类似的更改。
如果您没有strdup
或者您不允许使用它,则可以对其进行定义。这是一个非常简单的写作功能。
char* strdup(char const* in)
{
char* ret = new char[strlen(in)+1];
strcpy(ret, in);
return ret;
}