Я пытаюсь сделать глубокую копию (для копирования при записи) объекта, но получаю ошибку сегментации.
Я использую хеш-таблицу со связанным списком.
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;
РЕДАКТИРОВАТЬ: эта проблема, кажется, исправлена.
Что не так с моей глубокой копией? Я не понимаю Я думаю, что мой конструктор копирования хорош, но я не понимаю, почему я получаю ошибку сегмента при запуске.
Этот код должен быть исправлен:
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
,
Проблемы, которые я вижу:
Конструктор по умолчанию 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();
Затем стек памяти используется для хранения «Джона» в 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;
}