Я сейчас изучаю C ++ (начал как 2 дня назад), и у меня есть некоторые проблемы с написанием Copy C’tor of Node.
Узел является классом следующим образом:
template <class T>
class Node {
T* data;
Node<T>* next;
friend class Iterator<T>;
public:
Node():data(NULL),next(NULL){}
Node(const T& data):data(NULL),next(NULL){
T* copy = new T(data);
this->data = copy;
}
Node(const Node& node):data(NULL),next(NULL){
Node<T> dummy;
dummy.data = node.data;
dummy.next = node.next;
Node<T>* head=new Node(*dummy);
*this = *head;
while(dummy.next != NULL) {
dummy = *(dummy.next);
head = head->next;
head = new Node(*dummy);
}
}
Примечание: у меня есть оператор *, так что * фиктивные результаты в T-типе.
Еще одно примечание: мои публичные и приватные поля могут быть неправильными — но я рассмотрю это позже.
После того, как вы немного потрепали, давайте посмотрим на Copy C’tor, пожалуйста.
Он получает постоянную ссылку на Node, а затем я попытался создать указатель на него. Компилятор выдает ошибку:
Node<T>* dummy= &node;
Результаты invalid conversion from 'const Node<int>*' to 'Node<int>*'
(У меня есть короткая основная попытка создать Node<int>
).
Итак, похоже, что я не могу создать указатель на const, поэтому я попытался скопировать его поля вручную, как показано в коде.
Когда я запускаю отладчик Eclipse и проверяю, работает ли он — он работает.
Однако, когда я продолжаю делать шаги, вызывается D’tor голова (в конце конструктора копирования) и в результате все разваливается.
Поэтому я понятия не имею, что делать дальше, или даже если я на правильном пути.
Как мне сделать конструктор копирования? Я думаю, что понимаю, почему вызывается D’Tor (я что-то создал, и в конце блока что-то разрушено — верно?), Но я не знаю, как сделать это правильно.
Цель конструктора копирования — сделать «точную копию» переданного объекта. Так что в зависимости от семантики data
а также next
указатели, которые вы бы просто присвоили им, используя список инициализаторов:
Node(const Node& node): data(node.data), next(node.next) {}
Поскольку это так же, как ожидаемое поведение по умолчанию (члены копирования), вы можете просто опустить конструктор копирования, и компилятор сгенерирует подходящий конструктор по умолчанию.
Обратите внимание, что вы можете определенно создать указатель на const
object: на что жалуется компилятор, так это то, что объявление типа для вашего указателя теряет const
немного в процессе.
Второе замечание: для глубокой копии вы можете использовать что-то вроде:
Node(const Node& node):
data(node.data == NULL? NULL: new T(*node.data)),
next(node.next == NULL? NULL: new Node(*node.next)) {}
Конечно, в этом сценарии глубокого копирования ваш контейнер берет на себя «владение» полями-членами (что вызывает вопрос: почему они в первую очередь являются указателями?) И поэтому должен быть осторожен с delete
их в деструкторе.
Код, который вы разместили, не совсем соответствует заявлению, которое вы цитировали с ошибкой:
Node<T>* dummy= &node;
Но в любом случае, вы можете сделать это:
const Node<T>* dummy= &node;
Так как node
является const
любые ссылки или указатели на него также должны быть const
, Вы также не сможете вызывать неконстантные методы на node
поэтому любые методы, которые вы используете для методов доступа к данным, должны быть правильными.