为什么将对象作为指针传递但不在返回范围时超出范围

时间:2019-03-29 01:01:22

标签: c++ scope pass-by-reference pass-by-value

制作一个非常简单的链表,我发现自己对可能是一个非常简单的作用域概念感到困惑。第一部作品符合预期。似乎在第二个makeNode函数中,节点“ n”在终止时超出范围。我很困惑为什么会这样。

我很确定分配的内存仍然存在,并且这两种方法都有指向该内存的指针。那为什么不工作呢?

程序具有两个make节点功能

#include <iostream>
using namespace std;

struct Node
{
    int value;
    Node* next;
    Node() : next(NULL){}
};

Node* makeNode1(int value)
{
    Node* n = new Node;
    n->value = value;
    return n;
}

void makeNode2(int value, Node* mountPt)
{
    Node* n = new Node;
    n->value = value;
    mountPt = n;
}

void destroyNode(Node* mountPt)
{
    if(mountPt->next != NULL)
    {
        destroyNode(mountPt->next);
        delete mountPt;
    }
}

int main() {
    Node* origin = NULL;

    // This works
    origin = makeNode1(4);

    // causes a runtime error when dereferenced
    makeNode2(4, origin);

    return 0;
}

5 个答案:

答案 0 :(得分:2)

对于makeNode2,指针参数mountPt本身是按值传递的,那么在函数内部mountPt = n;指针本身的任何修改都与原始参数{ {1}}。

您可以将其更改为通过引用,即

origin

答案 1 :(得分:1)

在第一个实例中,您将创建一个新的内存部分,并带有指向该内存部分的指针(这只是一个地址),然后返回该地址。第二个示例传入一个指向内存中地址的指针,然后在函数范围内重新分配该地址(即更改该值)。但是,一旦函数退出,该指针的值(它所指向的地址)将返回到其先前的调用,因为该指针已在堆栈上具有一个值。区别在于,在第一次调用中,您更改了存储在最终从函数传递出去的地址中的值,而在第二次调用中,您更改了指针所指向的地址,但是指针又回到了指向旧地址的位置一旦将范围更改回主体。

答案 2 :(得分:0)

更改以下功能:

void makeNode2(int value, Node* mountPt)
{
    Node* n = new Node;
    n->value = value;
    if(mountPt) delete mountPt;
    mountPt = n;
}

如果已经分配了mountPt,它将被释放,然后origin可以指向分配n

答案 3 :(得分:0)

XY解决方案:通过扩展Node构造函数来消除对makeNode函数的需求

struct Node
{
    int value;
    Node* next;
    Node(int val = 0) :value(val), next(NULL){}
};

用法

Node * origin = new Node(4);

答案 4 :(得分:0)

尽管以上所有内容(包括接受的答案)都是相关的,但没有一个直接指出实际的逻辑缺陷。您需要$reservationBtn.unbind('click'); 来代替mountPt = n;