Передача указателя в функцию и ее изменение

0

Новый как для stackoverflow, так и для C/C++. Im работает через реализацию двоичного дерева и имеет простой вопрос. Допустим, у меня есть следующее:

struct Node {
    int data;
    Node* right_child;
    Node* left_child;
};

void addNode(Node* tree, int new_data){
    if(tree == NULL){
        Node* new_tree = new Node;
        new_tree->data = new_data;
        new_tree->right_child = NULL;
        new_tree->left_child = NULL;
        tree = new_tree;
    }
}

int main(){
    Node* tree = new Node;
    tree = NULL;
    addNode(tree, 3);
    cout << tree->data << endl; //CRASH
}

Довольно просто. Это приведет к сбою, потому что дерево все равно будет NULL, даже после возврата из addNode. я попытался понять, почему он не будет обновляться после вызова addNode. Конечно, копия указателя используется и обновляется, но не должен ли он по-прежнему содержать один и тот же адрес? Поэтому, все еще обновляйте исходный адрес памяти и возвращайтесь. Или новый указатель по какой-то причине указывает на другое местоположение? Я смущен тем, что происходит. Любая помощь будет замечательной.

Кроме того, я просто написал этот код на веб-сайте - извините, если ошибок мало, он действительно не запускал его.

Благодарю.

  • 1
    Почему вы устанавливаете tree в NULL сразу после его инициализации?
Теги:
pointers
function

3 ответа

4
Лучший ответ

Есть несколько проблем,

Во-первых, у вас есть локальная копия указателя addNode, и вы не addNode ссылку на нее, чтобы действовать на предмет, на который она указывает, но действуя непосредственно непосредственно на локальном указателе. new ed Node созданный внутри функции, просто потерян навсегда.

Вы можете исправить эту проблему, передав указатель по ссылке. Это не требует каких-либо изменений кода:

void addNode(Node*& tree, int new_data)

Во-вторых, как вы отметили, вы отменяете указатель NULL в main. Это просто неопределенное поведение (UB). Одна из вещей, которые могут произойти, - это крушение. Но код можно было просто запустить без сбоев. Важным фактом является то, что это UB, и на программу нельзя положиться.

Примечание 1: Если вы хотите инициализировать свой Node таким образом, чтобы элементы данных были инициализированы нулем, используйте инициализацию значения:

Node* tree = new Node();

Примечание 2: Будьте осторожны с использованием необработанных new указателей. У вас уже есть один два утечка ресурсов в вашем коде. Лучше использовать наиболее подходящий тип умного указателя.

  • 0
    Спасибо за помощь!
1

Благодаря этому вы передаете указатель на дерево в addNode

void addNode(Node* tree, int new_data)

выражение

tree = new_tree;

будет только локальным, вы не изменяете то, на что указывает прошедший указатель, поскольку дерево является копией указателя.

сравнить с

void foo(int n) {  n = 1; }   // local, n is a copy
void foo(int* n) { *n = 1; }  // change the original variabel

чтобы изменить то, что указывает дерево, вам нужно передать адрес указателя

void addNode(Node** tree, int new_data)
{
...
   *tree = new Node;
...
}
0

Если вы хотите, чтобы изменения отражались в вашей основной функции (для указателя или переменной без указателя), безопасный способ передает его по ссылке, поскольку ссылочные переменные могут быть инициализированы только один раз

т.е.:

void addNode(Node*& tree, int new_data)
{
   Node* tree_1;

   tree = &tree_1 //this can't be done
}

void addNode(Node** tree, int new_data)
{
   Node* tree_1;

   tree = &tree_1 //this can be done
}

Таким образом, самым безопасным способом является передача по ссылке, я имею в виду void addNode(Node*& tree, int new_data)

  • 0
    Это правда, что ссылки могут быть инициализированы только один раз, но это также верно для всего остального. В любом случае, строка с надписью «это не может быть сделано» на самом деле может быть сделано. Передача по ссылке - это исправление потребностей ОП, как объяснено в моем ответе.
  • 0
    Можете ли вы скомпилировать пример кода? для первой функции addNode компилятор сообщает Error '=': невозможно преобразовать из 'Node **' в 'Node *'
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню