刚学C++内存分配,对建立链表的疑问

铁锈_ 2016-08-31 09:30:45
刚刚学C++内存分配。回头看自己写的链表,产生了疑问。
函数返回值不可以是局部变量的指针或引用,因为当函数结束后局部变量被释放,那么指针将指向一个无效的内容(指针指向空间不变,但空间内容没有了)
那么为什么在建立链表返回头结点指针时却没发生这种问题。
其实链表的各个节点的空间都是在函数内建立的,包括头结点。
头结点的空间不应该在函数结束后释放么,导致头结点指针指向一个无效的空间,对其它节点也是这样
下面这句
newNodePtr = ( list* )malloc( sizeof( list ) ) ;
newNodePtr->element = data ;
newNodePtr->next = NULL ;
head = newNodePtr ;
函数结束后head指向的空间不会被释放掉么?头结点空间也是局部建立的啊?


#include <iostream>
#include <stdlib.h>
typedef struct Node list ;

struct Node
{
int element ;
struct Node *next;
} ;

using namespace std ;


list* creatList( )
{
int data ;
list *head ;
list *rearPtr ,*newNodePtr ;

head = NULL ;

while ( scanf("%d",&data) && data!=0 )
{
if( head == NULL )
{
newNodePtr = ( list* )malloc( sizeof( list ) ) ;
newNodePtr->element = data ;
newNodePtr->next = NULL ;
head = newNodePtr ;
rearPtr = head ;
}
else
{
newNodePtr = ( list* )malloc( sizeof( list ) ) ;
newNodePtr->element = data ;
newNodePtr->next = NULL ;
rearPtr->next = newNodePtr ;
rearPtr = newNodePtr ;//rearPtr永远指向尾节点
}
}
return head ;
}


void outPut( list *head )
{
if( head == NULL )
printf("链表为空\n");
else
while( head != NULL )
{
printf("%d ",head->element ) ;
head = head->next ;
}
printf("\n") ;
}

list* reverseList( list *head )
{
list *reverHead ;
list *t ;

reverHead = NULL ;

while( head!=NULL )
{
t = head->next ;
head->next = reverHead ;
reverHead = head ;
head = t ;
}
return reverHead ;
}




int main( )
{
list *head ;
head = creatList( ) ;

cout<<"原链表序列"<<endl ;
outPut( head ) ;

head = reverseList( head ) ;
cout<<"逆转后的链表序列"<<endl ;
outPut( head ) ;

return 0 ;
}
...全文
184 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
铁锈_ 2016-09-04
  • 打赏
  • 举报
回复
引用 5 楼 qq423399099 的回复:
一个由C/C++编译的程序占用的内存分为以下几个部分: 1、栈区(stack):又编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构的栈。 2、堆区(heap):一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事,分配方式倒是类似于数据结构的链表。malloc和new出来的空间就属于堆区。 3、全局区(static):也叫静态数据内存空间,存储全局变量和静态变量,全局变量和静态变量的存储是放一块的,初始化的全局变量和静态变量放一块区域,没有初始化的在相邻的另一块区域,程序结束后由系统释放。 4、文字常量区:常量字符串就是放在这里,程序结束后由系统释放。 5、程序代码区:存放函数体的二进制代码。
谢谢,明白了
铁锈_ 2016-09-04
  • 打赏
  • 举报
回复
引用 1 楼 woshirenjun12 的回复:
你得先去理解一下内存的划分,堆,栈,静态区等; 链表里面new出来的结点存在堆上,函数结束是不会释放的,只有手动调用delete才会被释放
谢谢,看了别人的博文
赵4老师 2016-08-31
  • 打赏
  • 举报
回复
其实电脑开机后物理内存的每个字节都是可读写的,从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页,一页通常为4KB。 栈中的变量通常包括函数参数和函数里声明的临时变量。 栈中的基本变量退出其作用域时,没有谁执行一段代码去释放/销毁/析构它所占用的内存,仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时,会自动执行其析构函数,……
lm_whales 2016-08-31
  • 打赏
  • 举报
回复
1)函数的返回值,不可以是局部(非静态)变量的地址,或者引用 ---------------跟指针没关系-------------------- 因为,局部(非静态)变量生命周期,不出函数。 一旦函数返回,则这个变量不可用了(生命周期结束) 返回他的地址,或引用,以求在函数调用结束后使用变量。 其实用的是变量的僵尸,而不是变量本身。 而这块内存,还可能,会被其他用途占用, 这样,就会使用造成程序混乱。 2)动态分配的内存(堆内存)并不是函数的局部(非静态)变量 确切的说,堆内存,是对程序员来说,一块没有名字的内存区域 这块内存本身,程序员是可以使用的, 但是要通过内存管理程序,进行分配,不用了要适时回收。 它本身,其实相当于全局变量。 所以生命周期,跟函数无关。 任何时候,只要没有回收, 读写都是可以的(只要不越界读写)
小灸舞 2016-08-31
  • 打赏
  • 举报
回复
一个由C/C++编译的程序占用的内存分为以下几个部分:

1、栈区(stack):又编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构的栈。

2、堆区(heap):一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事,分配方式倒是类似于数据结构的链表。malloc和new出来的空间就属于堆区。

3、全局区(static):也叫静态数据内存空间,存储全局变量和静态变量,全局变量和静态变量的存储是放一块的,初始化的全局变量和静态变量放一块区域,没有初始化的在相邻的另一块区域,程序结束后由系统释放。

4、文字常量区:常量字符串就是放在这里,程序结束后由系统释放。

5、程序代码区:存放函数体的二进制代码。
paschen 版主 2016-08-31
  • 打赏
  • 举报
回复
函数结束后,head指针变量自身被释放,其指向的内存不会被释放 malloc申请的内存不用free不会自动释放
qq_35578084 2016-08-31
  • 打赏
  • 举报
回复
你要学习下内存知识,使用new和malloc()分配的内存空间,只要进程不结束(无论以什么方式结束),或没有被手动释放,都不会被释放
starytx 2016-08-31
  • 打赏
  • 举报
回复
动态分配的(new ,c里边是malloc)需要程序员自己手动释放(delete,c对应的是free),也就是说不管在哪里new的,都一直保持有效。
IT_拖油瓶 2016-08-31
  • 打赏
  • 举报
回复
你得先去理解一下内存的划分,堆,栈,静态区等; 链表里面new出来的结点存在堆上,函数结束是不会释放的,只有手动调用delete才会被释放

64,650

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧