【问题标题】:confused with pointer to pointer concept与指针概念的指针混淆
【发布时间】:2014-10-31 19:10:50
【问题描述】:

传递指针基本上就像将指针作为值传递..函数内部对指针的更改不会修改指针的实际值..但是当我们需要在函数中访问实际指针本身时,那么我们就提出了指向指针的概念。这是我的理解..

            struct node
            {
                int data;
                struct node* next;
            };

            void push(struct node** head_ref, int new_data) // i understand the need of pointer to pointer here, since we are changing the actual value by adding a node..
            {
                struct node* new_node = (struct node*) malloc(sizeof(struct node));
                new_node->data  = new_data;
                new_node->next = (*head_ref);
                (*head_ref)    = new_node;
            }

            void insertAfter(struct node* prev_node, int new_data) // why are we not using pointer to pointer here since even here the pointer data is getting modified..??
            {
                if (prev_node == NULL)
                {

                  return;
                }

                struct node* new_node =(struct node*) malloc(sizeof(struct node));
                new_node->data  = new_data;
                new_node->next = prev_node->next;
                prev_node->next = new_node;
            }

            int main()
            {
                struct node* head = NULL;

                append(&head, 6);
                insertAfter(head->next, 8);

                return 0;
             }

请澄清.. 我很困惑为什么我们没有在 InsertAfter(...) 中使用指向指针的指针,以及认为我们在那里更改了指针?

【问题讨论】:

  • 在 C++ 中,不要在每次引用 struct 时重复 struct。另外,一般不要使用malloc。将构造函数添加到 structclass 类型后,这一点很重要。
  • "但是当我们需要在函数中访问实际指针本身时,我们就提出了指向指针的概念。这是我的理解.."这基本上是正确的,如果要从函数中更改指针值,则需要指向指针或引用指针的指针。虽然它看起来更像你怀疑或你的代码有一些问题。您对此有什么特别的疑问吗?
  • 是的..我把我的疑问放在代码中作为代码本身的注释..我想知道为什么 insertAfter(...) 没有指针?指向指针虽然它是变化的指针的值......为什么他们自己维护单指针概念......

标签: c++ pointers linked-list pointer-to-pointer


【解决方案1】:

不同之处在于函数对您传入的内容的作用。

这会修改 *head_ref 本身指向的内容:

void push(node** head_ref, int new_data);

虽然这会修改 prev_node 指向的 node 的内容,但它最终仍将指向相同的 node

void insertAfter(node* prev_node, int new_data);

查看实际使用情况也清楚这一点:

// head points to the node 0
node* head = new head{0, nullptr}; 

// head now points to the node 5, which itself points to the node 0
// so our list is {5} --> {0}
push(&head, 5); 
     ^
     additional clue that we are modifying head

// head->next points to the node 0 before this
// it **still** continues to point to that node after the call, but we 
// change what comes after it, to now be a new node 3
// so our list is {5} --> {0} --> {3}
insertAfter(head->next, 3);

// head is still the 5. head->next is still the 0. 

【讨论】:

  • 好的。假设我们有一个删除函数,它在最后删除一个节点。那么在这种情况下,我们不会更改节点的地址。那么按值传递就足够了吗? void DeleteAtEnd(struct node* node);
  • 是的。尽管您必须确保要删除的节点前面的节点将更新为指向要删除的节点之后的节点。
  • 你是说删除一个节点@front?如果我们删除@front,指针的地址会发生变化吗?那么它应该是一个指向指针的指针,如果我们想删除一个节点@end,那么它应该是一个单一的指针。我的理解正确吗?
  • 地址没有变化。我的意思是如果在列表为A --> B --> C 时删除节点B,则必须确保最终得到列表A --> C 而不是A --> {deleted pointer}。如果您的函数签名只是 void DeleteNode(node* );,那么单链表是不可能的
【解决方案2】:

一开始你是对的,但通常如果你想改变原始值,那么你通过引用(&)而不是值(*)传递指针

这里有一些东西可以阅读: http://courses.washington.edu/css342/zander/css332/passby.html

【讨论】:

    【解决方案3】:

    在第二个函数中你不是修改prev_node位置或地址,你只是改变数据。所以你只需要传值。

    【讨论】:

    • 好的。假设我们有一个删除函数,它在最后删除一个节点。那么在这种情况下,我们不会更改节点的地址。那么按值传递就足够了吗? void DeleteAtEnd(struct node* node);
    猜你喜欢
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2011-09-04
    相关资源
    最近更新 更多