C++中类和结构体的对象声明有两种方式:
- 直接声明的方式:
Node nodes;
这种方式声明的变量nodes
是创建在栈区的。由系统自动回收。
- 使用new的方式:
Node *nodes=new Node;
这种方式是创建在堆区的,是要程序员自己申请管理,系统不会自动回收。需要使用delete
回收。
下面看一段程序:
int main()
{
//create Linklist
Node nodes;
Node* node=&nodes;
nodes.val=0;
for(int i=1;i<5;i++)
{
Node nodei;
nodei.val=i;
node->next=&nodei;
node=node->next;
}
node->next=NULL;
printf("link list:\n");
Node* cur=&nodes;
while(cur!=NULL){
printfn
cur=cur->next;
}
}
上面这段程序的本意是要创建一个链表,0,1,2,3,4;但是最后的显示结果是:0,4
通过单步调试,查看变量地址信息,发现在进入循环后使用上述第一种方式创建的Node
变量每一次的地址都是相同的。
(gdb) p &nodei
$2 = (Node *) 0x7fffffffde50
(gdb) p &nodei
$3 = (Node *) 0x7fffffffde50
(gdb) c
Continuing.
Breakpoint 1, main () at getPenultimate_KNode.cpp:107
107 nodei.val=i;
(gdb) p &nodei
$4 = (Node *) 0x7fffffffde50
(gdb) p &nodei
$3 = (Node *) 0x7fffffffde50
(gdb) c
Continuing.
Breakpoint 1, main () at getPenultimate_KNode.cpp:107
107 nodei.val=i;
(gdb) p &nodei
$4 = (Node *) 0x7fffffffde50
本以为是应该每次申请一个新的变量的地址都不同的,但是事实告诉我们是相同的地址。猜测应该是变量名称相同,然后地址分配成了相同的地址。为了验证一些,做了如下测试:
int main()
{
//create linklist
Node node0;
Node* node=&node0;
node0.val=0;
Node node1;
node1.val=1;
node->next=&node1;
node=node->next;
Node node2;
node2.val=2;
node->next=&node2;
node=node->next;
node->next=NULL;
printf("link list:\n");
Node* cur=&node0;
while(cur!=NULL){
printf("%i\n",cur->val);
cur=cur->next;
}
}
这一次的结果正确了,因为不同的变量名称分配到了不同的地址,不会出现变量地址覆盖的问题。
或者使用new
的方式来申请新的Node
,这样每次申请的都是新的内存地址。
void LinkList::create(){
int temp;
cin>>temp;
Node* p=head;
while(temp!=-1){
Node *newNode=new Node;
newNode->val=temp;
newNode->next=NULL;
//connect to link list
p->next=newNode;
p=p->next;
//otherwise, it will in a infinite loop
cin>>temp;
}
}