与指针引用和指针混淆

时间:2016-06-21 10:05:46

标签: c++ pointers reference

我正在尝试创建一个单链表并在子表单中交换两个int元素 功能

  1. 在函数swap(int *a,int *b)中,参数类型为int *,它可以成功运行。
  2. 在函数build_sll(node *head)中,单个链接列表无法成功创建。
  3. 一旦我将参数类型设置为build_sll(node *&head),就会成功创建单链表。
  4. 困惑于:

    函数swap(int *a,int *b)已通过a b地址,我可以修改a b的值。  函数build_sll(node *head)仅传递指针head。我无法修改head的值。 为什么这里没有传递head地址。它们之间的唯一区别是它们的数据类型。

    在设置build_sll(node *head)之后,GDB我的代码之后,我发现所有node对象都已成功创建。在main中,如果我访问了分配的地址,它会记录node信息。在这种情况下如何删除内存。

    请参阅我的代码以明确我的问题。

    #include<iostream>
    #include<cstdlib>
    #include<memory.h>
    
    using namespace std;
    
    typedef struct node{
        int num;
        struct node * next;
    
        node(int num,struct node * next)
        {
            this->num = num;
            this->next = next;
        }
    
    }node;
    
    void build_sll(node *&head);
    void del_memory(node *&head);
    void travel_sll(node *head);
    void swap(int *,int *);
    
    int main()
    {
       int a =10 ,b = 5; 
       node *head = NULL;
    
        build_sll(head);
        travel_sll(head);
        del_memory(head);
    
        swap(&a,&b);
        cout << a <<"  "<< b <<"\n";
    
        exit(0);
    }
    
    void build_sll(node *&head)
    {
        head = new node(0,NULL);
        node * tail = head;
    
        for(int index = 1 ; index < 8;index++)
        {
             node * temp = new node(index,NULL);
             tail -> next = temp;
             tail = temp;
        }
    }
    
    void travel_sll(node *head)
    {
        if(head)
        {
            head = head -> next;
            while(head)
            {
                cout << head->num <<"\n";
                head = head -> next ;
            }
        }
    }
    
    void del_memory(node *&head)
    {
        delete [] head;
    }
    
    void swap(int *a,int *b)
    {
        int t;
        t = *a;
        *a = *b;
        *b = t;
    }
    

3 个答案:

答案 0 :(得分:1)

  

函数swap(int *a,int *b)传递了b的地址,我可以修改b的值。函数build_sll(node *head)仅传递指针头的值。我无法修改head的值。为什么这里没有通过头的地址。它们之间的唯一区别是它们的数据类型。

在功能swap中,您希望修改/访问int的值,以便通过int *int &。传递类型int的参数有助于读取参数的值,但是如果更改它,则只更新本地副本,而不是用于调用函数的值。

在函数build_sll中,您想要更改node *类型的参数。因此,您应该传递node **node *&类型的参数,以确保您可以在调用时更改值。传递node *只会更改本地副本(在被调用函数中),并且被调用函数中的原始值将保持不变。

您的选择是:

  • 优先node * build_sll(node *);
  • 确定node * build_sll(node *&);
  • 避免这种情况:node * build_sll(node **);

答案 1 :(得分:1)

  函数swap(int * a,int * b)传递了一个b的地址,我可以修改一个b的值。函数build_sll(node * head)只传递指针头的值。我无法修改head的值。为什么这里没有通过头的地址。它们之间的唯一区别是它们的数据类型。

好:

swap(&a,&b);

这里你传递a和b的地址 - 也就是说,你正在构造指向ab引用的值的指针,并将这些指针传递给swap函数的参数。

build_sll(head);

这里你传递了head的(恰好是指针变量)。传递的值指向某事(或为空),但它没有指向head本身引用的值。

如果您查看build_s11内部,假设它被声明为接收node *参数:

void build_sll(node *head)
{
    head = new node(0,NULL);

那么你不会把这个参数称为head - 但这很巧合。 它的意思是赋值只是改变参数变量的值,而不是原始变量的值。也就是说,head内的build_s11是调用表达式中{em>不同的变量到head;有两个变量,您正在修改函数内部的变量,而不是调用者中的变量

那么为什么它在swap中的行为方式不一样呢?好吧,根本区别在于build_s11swap指定参数变量本身,而在*a = *b; 中你指定给指针目标:

build_s11

如果要查看一致的行为,则应使用一致的语法。 void build_sll(node **head); 可以声明为:

build_sll(&head);

你会称之为:

node *

...然后你可以通过加入*head来改变传递指针void build_sll(node **head) { *head = new node(0,NULL); node * tail = *head; 值的值:

swap

...等请注意,它现在已经保持一致:就像*a中您使用*ba一样(而不是普通b和{{1} }),您现在在*head使用build_s11(而不是head)。

当然,您也可以使用引用,就像您在完整代码发布中所做的那样。

答案 2 :(得分:1)

如果我正确理解了第一个问题,您会感到困惑,为什么可以通过指针修改ab的值,并且无法修改head的值相同的语法。

如果是这种情况,则会发生这种情况,因为ab的类型为int,而int *a指向内存中变量的地址,因此使您能够通过取消引用修改功能。您可以像这样实现swap函数:

void swap(int &a,int &b)
{
    int t;
    t = a;
    a = b;
    b = t;
}

swap(a,b)可行。

正如您所注意到的,head的数据类型不同,它是node *。要修改它的值,您需要一个指向存储器地址的指针,其中存储指针本身。因此,您需要传递对node *head的引用以进行修改。 build_sll函数也可以通过解除引用来实现

void build_sll(node **head)
{
    *head = new node(0,NULL);
    node * tail = head;

    for(int index = 1 ; index < 8;index++)
    {
         node * temp = new node(index,NULL);
         tail -> next = temp;
         tail = temp;
    }
}

但是,使用双指针的语法不是首选,因为它会导致不断使用解引用,因此最好使用&语法