C++ 理解指针的问题

C++ 理解指针的问题,c++,pointers,C++,Pointers,以下代码摘自《编程访谈》一书 我很难理解指针的概念。为什么我们不能使用代码1 代码1 bool insertInFront( IntElement *head, int data ) { IntElement *newElem = new IntElement; if( !newElem ) return false; newElem->data = data; head = newElem; // Incorrect! return true; }

以下代码摘自《编程访谈》一书 我很难理解指针的概念。为什么我们不能使用代码1

代码1

bool insertInFront( IntElement *head, int data )
{
    IntElement *newElem = new IntElement;
    if( !newElem ) return false;
    newElem->data = data;
    head = newElem; // Incorrect!
    return true;
}
代码2

bool insertInFront( IntElement **head, int data )
{
    IntElement *newElem = new IntElement;
    if( !newElem ) return false;
    newElen->data = data;
    *head = newElem; // Correctly updates head
    return true;
}

要在函数调用之外更改通过函数参数传递的任何内容的值(并保持该更改),必须具有要更改其值的内容的内存地址。这是表示必须“按引用传递”而不是“按值传递”的另一种方式——否则,按值传递将导致函数仅更改副本。

要在函数调用之外更改通过函数参数传递的任何内容的值(并保持该更改),您必须拥有要更改其值的内存地址。这是另一种说法,即必须“按引用传递”而不是“按值传递”——否则,按值传递将导致函数仅更改副本。

指针的概念非常复杂。基本上,您需要考虑指针的方式是,它们本身就是“值”。因此:

*head = some_memory_address_that_points_to_head;
可以被认为是:

int im_a_pointer_to_head = some_memory_address_value_to_head;
因此,如果我们将相同的概念应用于第一个函数:

bool insertInFront(int im_a_pointer_to_head, int data)...
实际上,您传递的是头指针值的副本,在函数中更改它只会更改为此函数创建的临时副本,实际上不会更改原始指针指向的位置


第二个函数解决了这个问题,因为您实际上是在传递指针的副本,该副本指向指向头部的指针(试着说快3倍!)。在这种情况下,您不会更改复制的值,而是更改实际指针指向的位置。

指针的概念非常复杂。基本上,您需要考虑指针的方式是,它们本身就是“值”。因此:

*head = some_memory_address_that_points_to_head;
可以被认为是:

int im_a_pointer_to_head = some_memory_address_value_to_head;
因此,如果我们将相同的概念应用于第一个函数:

bool insertInFront(int im_a_pointer_to_head, int data)...
实际上,您传递的是头指针值的副本,在函数中更改它只会更改为此函数创建的临时副本,实际上不会更改原始指针指向的位置

第二个函数解决了这个问题,因为您实际上是在传递指针的副本,该副本指向指向头部的指针(试着说快3倍!)。在这种情况下,您不会更改复制的值,而是更改实际指针指向的位置。

  • 在代码1中,您将
    newElem
    的指针位置分配给
    头的本地副本。当函数返回时,
    head
    被销毁,并且您将发生内存泄漏(您丢失了指向
    newElem
    的指针,无法
    删除它。)您只更改了函数的指针本地副本,调用方的副本不受影响

  • 在代码2中,
    head
    是指向指针的指针。你不仅有一个指针,实际上还有一个指向调用方指针的指针。这允许您更改调用方的指针,存储指向
    newElem
    的指针。当函数返回时,
    head
    被销毁,但它只是指向指针的指针。原始指针在调用方的作用域中是完整的

      • 在代码1中,您将
        newElem
        的指针位置分配给
        头的本地副本。当函数返回时,
        head
        被销毁,并且您将发生内存泄漏(您丢失了指向
        newElem
        的指针,无法
        删除它。)您只更改了函数的指针本地副本,调用方的副本不受影响

      • 在代码2中,
        head
        是指向指针的指针。你不仅有一个指针,实际上还有一个指向调用方指针的指针。这允许您更改调用方的指针,存储指向
        newElem
        的指针。当函数返回时,
        head
        被销毁,但它只是指向指针的指针。原始指针在调用方的作用域中是完整的


      假设您正在调用函数1:

      insertInFront(H, data);
      
      调用函数时,计算机复制参数,然后在函数返回时释放它们。因此,在代码1中,
      head=newElem
      newElem
      的地址分配给
      head
      (它是
      H
      的副本),然后释放
      head
      ,而
      newElem
      的地址将永远丢失。 但是,在代码2中,该函数应被称为:

      insertInFront(&H, data);
      

      这意味着
      H
      的地址被复制到
      head
      ,而
      newElem
      的地址被分配到
      *head
      ,即
      head
      指向的位置,从而导致
      H
      。通过这种方式,您可以在函数返回后获得
      newElem
      的地址。

      假设您正在调用函数1,如下所示:

      insertInFront(H, data);
      
      调用函数时,计算机复制参数,然后在函数返回时释放它们。因此,在代码1中,
      head=newElem
      newElem
      的地址分配给
      head
      (它是
      H
      的副本),然后释放
      head
      ,而
      newElem
      的地址将永远丢失。 但是,在代码2中,该函数应被称为:

      insertInFront(&H, data);
      

      这意味着
      H
      的地址被复制到
      head
      ,而
      newElem
      的地址被分配到
      *head
      ,即
      head
      指向的位置,从而导致
      H
      。通过这种方式,您可以在函数返回后获得
      newElem
      的地址。

      使用指针实现引用语义的基本规则:调用方获取地址,被调用方取消引用。尝试更简单的方法。