刚刚学C++内存分配。回头看本人写的链表,产生了疑问。
函数返回值不可以是局部变量的指针或引用,原因是当函数结束后局部变量被释放,那么指针将指向一个无效的内容(指针指向空间不变,但空间内容没有了)
那么为什么在建立链表返回头结点指针时却没发生这种问题。
其实链表的各个节点的空间都是在函数内建立的,包括头结点。
头结点的空间不应该在函数结束后释放么,导致头结点指针指向一个无效的空间,对其它节点也是这样
下面这句
newNodePtr = ( list* )malloc( sizeof( list ) ) ;
newNodePtr->element = data ;
newNodePtr->next = NULL ;
head = newNodePtr ;
函数结束后head指向的空间不会被释放掉么?头结点空间也是局部建立的啊?
函数返回值不可以是局部变量的指针或引用,原因是当函数结束后局部变量被释放,那么指针将指向一个无效的内容(指针指向空间不变,但空间内容没有了)
那么为什么在建立链表返回头结点指针时却没发生这种问题。
其实链表的各个节点的空间都是在函数内建立的,包括头结点。
头结点的空间不应该在函数结束后释放么,导致头结点指针指向一个无效的空间,对其它节点也是这样
下面这句
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 ; }
解决方案
5
你得先去理解一下内存的划分,堆,栈,静态区等;
链表里面new出来的结点存在堆上,函数结束是不会释放的,只有手动调用delete才会被释放
链表里面new出来的结点存在堆上,函数结束是不会释放的,只有手动调用delete才会被释放
5
动态分配的(new ,c里边是malloc)需要程序员本人手动释放(delete,c对应的是free),也就是说不管在哪里new的,都一直保持有效。
2
你要学习下内存知识,使用new和malloc()分配的内存空间,只要进程不结束(无论以什么方式结束),或没有被手动释放,都不会被释放
10
一个由C/C++编译的程序占用的内存分为以下几个部分:
1、栈区(stack):又编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式相似于数据结构的栈。
2、堆区(heap):一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事,分配方式倒是相似于数据结构的链表。malloc和new出来的空间就属于堆区。
3、全局区(static):也叫静态数据内存空间,存储全局变量和静态变量,全局变量和静态变量的存储是放一块的,初始化的全局变量和静态变量放一块区域,没有初始化的在相邻的另一块区域,程序结束后由系统释放。
4、文字常量区:常量字符串就是放在这里,程序结束后由系统释放。
5、程序代码区:存放函数体的二进制代码。
1、栈区(stack):又编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式相似于数据结构的栈。
2、堆区(heap):一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事,分配方式倒是相似于数据结构的链表。malloc和new出来的空间就属于堆区。
3、全局区(static):也叫静态数据内存空间,存储全局变量和静态变量,全局变量和静态变量的存储是放一块的,初始化的全局变量和静态变量放一块区域,没有初始化的在相邻的另一块区域,程序结束后由系统释放。
4、文字常量区:常量字符串就是放在这里,程序结束后由系统释放。
5、程序代码区:存放函数体的二进制代码。
3
1)函数的返回值,不可以是局部(非静态)变量的地址,或引用
–跟指针没关系–
原因是,局部(非静态)变量生命周期,不出函数。
一旦函数返回,则这个变量不可用了(生命周期结束)
返回他的地址,或引用,以求在函数调用结束后使用变量。
其实用的是变量的僵尸,而不是变量本身。
而这块内存,还可能,会被其他用途占用,
这样,就会使用造成程序混乱。
2)动态分配的内存(堆内存)并不是函数的局部(非静态)变量
确切的说,堆内存,是对程序员来说,一块没有名字的内存区域
这块内存本身,程序员是可以使用的,
但是要通过内存管理程序,进行分配,不用了要适时回收。
它本身,其实相当于全局变量。
所以生命周期,跟函数无关。
任何时候,只要没有回收,
读写都是可以的(只要不越界读写)
–跟指针没关系–
原因是,局部(非静态)变量生命周期,不出函数。
一旦函数返回,则这个变量不可用了(生命周期结束)
返回他的地址,或引用,以求在函数调用结束后使用变量。
其实用的是变量的僵尸,而不是变量本身。
而这块内存,还可能,会被其他用途占用,
这样,就会使用造成程序混乱。
2)动态分配的内存(堆内存)并不是函数的局部(非静态)变量
确切的说,堆内存,是对程序员来说,一块没有名字的内存区域
这块内存本身,程序员是可以使用的,
但是要通过内存管理程序,进行分配,不用了要适时回收。
它本身,其实相当于全局变量。
所以生命周期,跟函数无关。
任何时候,只要没有回收,
读写都是可以的(只要不越界读写)