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

私のクラス Hashtable の属性:

 Person **table;
    int* num;

編集: この問題は修正されたようです。 ディープ コピーの何が問題になっていますか? 理解できない。私のコピー コンストラクターは優れていると思いますが、実行するとセグ フォールトが発生する理由がわかりません。

4

2 に答える 2

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によって保持されるようにaなり、未定義の動作が発生します。

    入力文字列の所有権を取得する必要があります。の代わりにstd::stringforを使用します。idchar const*

  2. のコンストラクタをコピーしPersonます。

    ステートメント

    id(rhs.id),
    

    char const*の型として使用することにした場合、問題になりますid。に切り替えればstd::string問題ありません。

  3. のコピー コンストラクターはHashTable、 の浅いコピーを作成しtableます。tableのデストラクタでを削除することにした場合、これは問題になりますHashTabletableのデストラクタで削除しないHashTableと、メモリ リークが発生します。

  4. では、逆参照する前に NULLdeepcopyかどうかをチェックしていません。array[i]これはすでに @alphashooter によって指摘されています。さらに、関数のローカル変数にディープ コピーを作成していますautre。ディープ コピーは、関数から戻らない限り、関数の外では表示されませんautre

EDIT を使用することは許可されていないため、コピー コンストラクターだけでなく、デフォルト コンストラクターにも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 に答える