我正在尝试创建一个单链表并在子表单中交换两个int
元素
功能
swap(int *a,int *b)
中,参数类型为int *
,它可以成功运行。build_sll(node *head)
中,单个链接列表无法成功创建。build_sll(node *&head)
,就会成功创建单链表。困惑于:
函数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;
}
答案 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的地址 - 也就是说,你正在构造指向a
和b
引用的值的指针,并将这些指针传递给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_s11
在swap
指定参数变量本身,而在*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
中您使用*b
和a
一样(而不是普通b
和{{1} }),您现在在*head
使用build_s11
(而不是head
)。
当然,您也可以使用引用,就像您在完整代码发布中所做的那样。
答案 2 :(得分:1)
如果我正确理解了第一个问题,您会感到困惑,为什么可以通过指针修改a
和b
的值,并且无法修改head
的值相同的语法。
如果是这种情况,则会发生这种情况,因为a
和b
的类型为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;
}
}
但是,使用双指针的语法不是首选,因为它会导致不断使用解引用,因此最好使用&
语法