首页 > 解决方案 > 如果指针在函数内被修改,为什么要返回指向对象的指针?

问题描述

我从 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 没有成功设置左节点,右节点也是如此。

标签: c++data-structures

解决方案


您正在返回一个指向局部变量的指针,该变量的生命周期已经结束。

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>or std::shared_ptr<treeNode>,因为它更难意外地作为悬空指针留下。或者,如果您必须使用原始指针,那么您至少需要treeNode使用关键字创建一个对象new,以便其生命周期可以比函数调用持续更长的时间。


推荐阅读