-1

我正在尝试对对象进行深层复制(用于写入时复制),但出现分段错误。

我正在使用带有链表的哈希表。

    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;
}

我的班级哈希表的属性:

 Person **table;
    int* num;

编辑:这个问题似乎是固定的。 我的深层副本有什么问题?我不明白。我认为我的复制构造函数很好,但我不明白为什么在运行它时会出现段错误。

4

2 回答 2

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.

于 2014-04-16T23:04:07.423 回答
0

我看到的问题:

  1. 的默认构造函数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();
    

    然后用于保存“John”的堆栈内存foo现在由 by 保存a,这将导致未定义的行为。

    您需要拥有输入字符串的所有权。使用std::stringforid代替char const*.

  2. 的复制构造函数Person

    该声明

    id(rhs.id),
    

    如果您决定使用char const*as 类型,那将是一个问题id。如果切换到std::string,则不会有问题。

  3. 的复制构造函数HashTabletable. 如果您决定table删除HashTable. 如果你不在table析构函数中删除HashTable,你就有内存泄漏。

  4. 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;
}
于 2014-04-16T23:32:39.133 回答