Получение этой ошибки при попытке передать указатель по ссылке

Я пытаюсь сделать функцию удаления узла в BST, и мне нужно передать указатель по ссылке, чтобы я мог изменить указатель, но я продолжаю получать эту ошибку:

'void Tree::deletNode(T,Node *&)': невозможно преобразовать аргумент 2 из 'Node *' в 'Node *&'

Есть 2 из этих ошибок, и они происходят в deletNode при рекурсивном вызове самого себя.

Программа запускается, когда у меня нет &, но она не работает должным образом.

Это две мои функции, которые должны удалить узел в BST. корневой указатель дерева называется корневым, а узел — типом узла. Также вызывается функция deletNode, которая вызывает makedelete. но пользователь вызывает deletNode

    void deletNode(T num, Node<T> *& nodeptr)
{
    if (num < nodeptr->getData())
        deletNode(num, nodeptr->getLeft());
    else if (num > nodeptr->getData())
        deletNode(num, nodeptr->getRight());
    else
    {
        cout << "called makedelete on " << nodeptr << "which has " << nodeptr->getData() << endl;
        makedelete(nodeptr);
    }
}

void makedelete(Node<T> *& nodeptr)
{
    Node<T> * tempnode;

    if (nodeptr == nullptr)
        cout << "error..." << endl;
    else if (nodeptr->getRight() == nullptr)
    {
        tempnode = nodeptr;
        nodeptr = nodeptr->getLeft();
        delete tempnode;
    }
    else if (nodeptr->getLeft() == nullptr)
    {
        tempnode = nodeptr;
        nodeptr = nodeptr->getRight();
        delete tempnode;
    }
    else //has 2 kids
    {
        tempnode = nodeptr->getRight(); ///move 1 node to right

        while (tempnode->getLeft()) // go to end of left
        {
            tempnode = tempnode->getLeft();
        }

        tempnode->setLeft(nodeptr->getLeft());
        tempnode = nodeptr;
        nodeptr = nodeptr->getRight();
        delete tempnode;

    }
}

};

Вот класс узла:

template <typename T>
class Node
{
    T data;
    Node* left;
    Node* right;
public:
    T getData() { return data; }
    Node<T>* getLeft() { return left; }
    Node<T>* getRight() { return right; }
    void setData(T t) { data = t; }
    void setLeft(Node<T>* pLeft) { left = pLeft; }
    void setRight(Node<T>* pRight) { right = pRight; }
};

person fman    schedule 27.02.2016    source источник
comment
Прочтите Как создать минимальный, полный и проверяемый пример   -  person OldProgrammer    schedule 28.02.2016
comment
Что-то не так с постом?   -  person fman    schedule 28.02.2016
comment
Да. Вы не показываете определение Node — его элементы данных и функции.   -  person OldProgrammer    schedule 28.02.2016
comment
ОК, я добавил класс узла   -  person fman    schedule 28.02.2016
comment
фман. Прочтите инструкции, которые вам дали.   -  person Lightness Races in Orbit    schedule 28.02.2016
comment
Вы также должны вычитывать вещи и использовать предварительный просмотр вашего сообщения, до того, как вы фактически будете вносить сообщения и/или будущие изменения.   -  person code_dredd    schedule 28.02.2016
comment
Я не понимаю, в чем проблема с моим кодом   -  person fman    schedule 28.02.2016


Ответы (2)


Node<T>* getLeft() { return left; }

Это возвращается по значению. Таким образом, возвращенный Node<T>* является временным. Обратите внимание: поскольку вы возвращаете значение left, а не ссылку на left или указатель на left, вы не можете изменить left, вызвав getLeft.

void deletNode(T num, Node<T> *& nodeptr)

Это принимает неконстантную ссылку на Node<T>*.

    deletNode(num, nodeptr->getLeft());

Здесь вы пытаетесь вызвать deletNode во временном, возвращенном getLeft. Но вы не можете привязать неконстантную ссылку к временной. Вы не можете изменить left через возврат getLeft, потому что он не возвращает ни ссылку, ни указатель.

Исправление зависит от того, что вы действительно хотите сделать, но это определенно не попытка передать временное значение функции, которая принимает неконстантную ссылку. Вы ожидаете, что вызов deletNode изменит nodeptr->left? Если это так, getLeft должен вернуть ссылку.

person David Schwartz    schedule 28.02.2016
comment
Другая проблема заключается в том, что после всего этого left является висячим указателем (не уверен, что OP знает, что left не будет установлено значение null). Весь дизайн deletNode - барахло - person M.M; 28.02.2016
comment
Спасибо, это имеет смысл. !!! Это сообщение об ошибке казалось, что ошибка была чем-то другим. - person fman; 28.02.2016
comment
Что касается висячего указателя, в функции makedelete есть функция удаления, которая удалит указатель. - person fman; 28.02.2016

Что происходит, так это то, что nodeptr->getLeft() или nodeptr->getRight() приведет к rvalue, и вы пытаетесь сохранить ссылку на rvalue, которая неверна. из него в deletNode..

Прежде чем вы сможете передать его в deletNode, сделайте это

Node<int>* tmp = node->getLeft();
deletNode(tmp);

Вы можете сохранить ссылку на rvalue в С++ 11, для этого измените подпись deletNode на

void deletNode(Node<T> *&& nodeptr)
person Sam Daniel    schedule 27.02.2016
comment
Вы, конечно, имеете в виду deleteNode(tmp)? - person user207421; 28.02.2016
comment
Ваше второе предложение будет означать, что функция больше не работает для lvalues. - person M.M; 28.02.2016
comment
Благодарю вас! Это еще один способ решения проблемы. К сожалению, я пока не могу проголосовать - person fman; 28.02.2016