2015-12-28 2 views
0

У меня возникли проблемы с написанием конструктора копий для моей хэш-таблицы. У меня уже возникли проблемы с конструкторами копирования со связанными объектами. Как можно реализовать конструктор копирования и оператор присваивания со следующими функциями:копии конструкторов для хэш-таблиц

//copy constructor 
Apple::Apple(const Apple& anotherApple){ 


} 

//assignment operator 
Apple& Apple::operator = (const Apple& anotherApple){ 


} 

Я знаю, что это было бы что-то вдоль линий:

tableSize = anotherApple.tableSize; 
count = anotherApple.count; 
array = new *anotherApple.array; //idk if this is right for dynamically created array of pointers 
+0

массив = новый узел * [таблицаSize]. Но вам нужно знать количество элементов, которые будут помещены в каждую строку. Для выполнения глубокой копии необходимо выполнить итерацию по другому элементу apple.array и скопировать все элементы по одному для каждой строки. Это имеет смысл для вас? –

+0

@pravar, как бы вы сделали глубокую копию. Потому что мне нужно скопировать каждый связанный узел по каждому индексу массива? – programmingblues

+0

Совет - сосредоточьтесь только на конструкторе копирования. Оператор присваивания можно легко записать, как только конструктор копирования (и деструктор) работают правильно. Во-вторых, ваш массив должен знать, сколько элементов нужно выделить первым, и это должно быть доступно из 'anotherApple'. – PaulMcKenzie

ответ

1
Apple::Apple(Apple const & anotherApple) 
{ 
    // allocate an array to hold pointers to Node 
    array = new Node*[tableSize]; 

    for(int i=0; i<tableSize; i++) 
    { 
     Node* src = anotherApple.array[i]; 
     Node* dest; 

     if (src == NULL) 
     { 
      array[i] = NULL; 
      continue; // no data to copy, continue to next row 
     } 


     // set array[i] since there is at-least one element 
     dest = new Node; 
     dest->data = src->data; 

     array[i] = dest; 
     src = src->next; 

     while(src != NULL) 
     { 
      Node* n = new Node; 
      dest->next = n; 
      dest = n; 

      dest->data = src->data; 

      src = src->next; 
     } 

     dest->next = NULL; 
    } 
    } 
+0

Если OP имеет функцию «добавить», почти весь этот код можно устранить. – PaulMcKenzie

+0

Да. Но я не предполагал ничего. Но, конечно, это может быть значительно упрощено. Сейчас это довольно грязно. –

+0

@pravar извините, но можете ли вы прокомментировать свой код, чтобы я мог легко следить за тем, что вы пытаетесь сделать? – programmingblues

1

Теоретически, ваш конструктор копирования может записываться в цикле, при условии, что существуют правильные функции при извлечении из хэш-таблицы и добавление значения в хеш-таблицу. Если этих функций в настоящее время не существует, тогда было бы намного дороже, если бы вы все равно записывали эти функции, так как хеш-таблица была бы очень ограничительной, если бы не было способа повторить все значения.

Предположим, что у вас есть такие функции, в которых вы получаете Node* в функциях get. Также предположим, что getFirst() извлекает головной узел, а getNext() извлекает следующий узел, учитывая значение Node* для начала. Конструктор копирования будет выглядеть примерно так:

Apple::Apple(const Apple& anotherApple) 
{ 
    Node* curNode = anotherApple.getFirst(); 
    while (curNode) 
    { 
     addValue(curNode->key, curNode->value); 
     curNode = anotherApple.getNext(curNode); 
    } 
} 

Это требует, чтобы ваша реализации есть способ, чтобы получить первое значение в таблице, используя что-то вроде getFirst() и итерации к следующей записи текущего узла с помощью функции getNext(). Если не больше узлов, то getNext() вернет NULL.

Преимущество написания конструктора копирования таким образом заключается в том, что вы повторно используете код, который, мы надеемся, был протестирован, а именно функцию addValue, вместо того, чтобы в принципе переписать addValue снова. Кроме того, вероятность возникновения ошибки практически отсутствует, поскольку вы просто вызываете уже существующие функции.

Недостаток написания конструктора копирования таким образом заключается в том, что сложность с точки зрения runtiime может быть медленнее, чем попытка создания всех внутренних компонентов «с нуля» с использованием большого количества манипуляций с указателями (как это сделал один из предыдущих ответов).

Так взвесить разницу, безопасность по скорости. Возможно, нет проблем с безопасностью, используя безопасный подход.


Для оператора присваивания, если у вас есть рабочий конструктор копирования и рабочий деструктор, то это все, что вам нужно сделать:

#include <algorithm> 
//... 
Apple& Apple::operator=(const Apple& anotherApple) 
{ 
    Apple temp(anotherApple); 
    std::swap(temp.array, array); 
    std::swap(temp.tableSize, tableSize); 
    std::swap(temp.count, count); 
    return *this; 
} 

Это использует copy/swap idiom. Опять же, для этого требуется правильный конструктор копирования и правильный деструктор (никаких ошибок в этих двух функциях).

Смежные вопросы