Зачем возвращать указатель на объект, если указатель изменяется внутри функции? - PullRequest
0 голосов
/ 11 ноября 2018

Я нашел этот фрагмент кода от GeeksForGeeks об импорте узлов в дерево из массива-представления дерева.

Я пытался реализовать свою собственную версию, но не смог заставить ее работать. Затем я понял, что должен вернуть Node * (в моей собственной версии: treeNode *).

Зачем мне это делать, если я уже изменяю указатель (корень) внутри функции?

От GeeksForGeeks:

// Function to insert nodes in level order 
Node* insertLevelOrder(int arr[], Node* root, int i, int n) 
{ 
    // Base case for recursion 
    if (i < n) 
    { 
        Node* temp = newNode(arr[i]); 
        root = temp; 

        // insert left child 
        root->left = insertLevelOrder(arr, 
                   root->left, 2 * i + 1, n); 

        // insert right child 
        root->right = insertLevelOrder(arr, 
                  root->right, 2 * i + 2, n); 
    } 
    return root; 
} 

Моя собственная версия:

treeNode* import_treeNode(treeNode* root, int nodes[], int curr_i, int size){
    if (curr_i < size){
        treeNode newNode = treeNode(nodes[curr_i]);
        root = &newNode;
        root->left = import_treeNode(root->left, nodes, 2 * curr_i + 1, size);
        root->right = import_treeNode(root->right, nodes, 2 * curr_i + 2, size);
    }
    return root;
}

Моя версия не работает, потому что она успешно не возвращает treeNode с установленными значениями. Я могу убедиться, что конструктор treeNode работает. Проблема заключается в том, что root-> left = import_treeNode не может правильно установить левый узел, и то же самое для правого узла.

1 Ответ

0 голосов
/ 11 ноября 2018

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

treeNode* import_treeNode(treeNode* root, int nodes[], int curr_i, int size){
    if (curr_i < size){
        // The lifetime of "newNode" begins when its constructor completes.
        treeNode newNode = treeNode(nodes[curr_i]);
        root = &newNode;
        // Now root points at newNode.
        root->left = import_treeNode(root->left, nodes, 2 * curr_i + 1, size);
        root->right = import_treeNode(root->right, nodes, 2 * curr_i + 2, size);
        // The above are the same as just assigning newNode.left and newNode.right.

        // Here the destructor is invoked for "newNode", and its lifetime ends.
    }
    // Returns a dangling pointer, which once pointed at newNode.
    // Using that pointer in almost any way results in undefined behavior.
    return root;
}

Было бы лучше использовать std::unique_ptr<treeNode> или std::shared_ptr<treeNode>, которые сложнее случайно оставить как висячие указатели. Или, если вам нужно использовать необработанные указатели, вам, по крайней мере, нужно создать объект treeNode с помощью ключевого слова new, чтобы его время жизни могло длиться дольше, чем вызов функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...