动态内存的传递

2015/06/22 C和C++基础

C/C++编程时,会多次与内存管理打交道,因此掌握内存分配、传递、赋值与释放等知识十分必要。

32.各种内存分配和释放的函数的联系和区别

解析:

C语言的标准内存分配函数有malloc、calloc、realloc、free等。

malloc与calloc的区别如下:

malloc调用形式为:

(类型*)malloc(size)

在内存的动态存储区中分配长度为“size”字节的连续区域,返回该区域的首地址,此时内存中的值没有初始化,是一个随机数。

calloc调用形式为:

(类型*)calloc(n,size)

在内存的动态存储区中分配n块长度为“size”字节的连续区域,返回首地址,此时内存中的值都被初始化为0。

realloc调用形式为:

(类型*)realloc(*ptr,size)

将ptr内存大小增大到“size”,增加的内存块没有初始化。

free的调用形式为free(void *ptr):释放ptr所指向的内存空间。

C++中用new和delete函数,调用类的构造函数和析构函数。

33.程序找错–动态内存的传递
#include <iostream>
using namespace std;

class Base{
private:
	char* name;
public:
	Base(char* className){
		name=new char[strlen(className)];   //sizeof
		strcpy(name,className);
	}	
	~Base(){
		delete name;
	}
	char* copyName(){
		char newname[10]="";
		strcpy(newname,name);
		return newname;
	}
	char* getName(){
		return name;
	}
};

class Subclass:public Base{
public:
	Subclass(char* className):Base(className){}
}

int main(){
	Base *pBase=new Subclass("test");
	printf("name:%s\n",pBase->getName());
	printf("new name:%s\n",pBase->copyName());
	return 0;
}

代码:

name=new char[strlen(className)+1];

改为:

char *newname=new char[strlen(name)+1];
程序分析改错–动态内存的传递
#include <iostream>

using namespace std;

void GetMemory(char *p,int num){
	p=(char*)malloc(sizeof(char)*num);
}

int main(){
	char *str=NULL;
	GetMemory(str,10);
	strcpy(str,"hello");
	cout<<str<<endl;
	system("pause");
}

解析:

GetMemory()函数存有错误。因为编译器总是为函数的每个参数制作临时的变量。所以GetMemory()函数体内的p是main函数中str变量在GetMemory()函数中的一个备份。虽然代码p申请了堆内存,但是返回到main()函数时,str还是NULL,而不指向对内存,因此在调用strcpy时会导致程序崩溃。

同时,GetMemory()申请堆内存没有释放。

采用以下3种方法来解决动态内存不能传递的问题。

1.在C中,采用指向指针的指针解决这个问题,可以把str的地址传给GetMemory()函数。

2.在C++中,采用传递str指针的引用。

3.使用函数返回值来传递动态内存。

如:

#include <iostream>

using namespace std;

void GetMemory(char *p,int num){
	p=(char*)malloc(sizeof(char)*num);
}

void GetMemory2(char **p,int num){        //指针的指针
	*p=(char*)malloc(sizeof(char)*num);
}

void GetMemory3(char *&p,int num){        //引用
	p=(char*)malloc(sizeof(char)*num);
}
 
char* GetMemory4(int num){                //返回指针
	char *p=(char*)malloc(sizeof(char)*num);
	return p;
}

int main(){
	char *str1=NULL;
	char *str2=NULL;
	char *str3=NULL;
	char *str4=NULL;

	GetMemory2(&str2,20);
	GetMemory3(str3,20);
	str4=GetMemory4(20);

	strcpy(str2,"GetMemory2");
	strcpy(str3,"GetMemory3");
	strcpy(str4,"GetMemory4");

	cout<<"str1==NULL?"<<(str1==NULL?"yes":"no")<<endl;
	cout<<"str2:"<<str2<<endl;
	cout<<"str3:"<<str3<<endl;
	cout<<"str4:"<<str4<<endl;

	free(str2);
	free(str3);
	free(str4);
	str2=NULL;       //防止野指针出现
	str3=NULL;
	str4=NULL;     
	system("pause");
}

程序运行结果:

35.比较分析两个代码段的输出–动态内存传递

程序1:

char* GetMemory(){
	char p[]="hello world";  //局部变量
	return p;
}

void Test(void){
	char *str=NULL;
	str=GetMemory();
	printf(str);             //输出乱码
}

程序2:

void GetMemory(char *p){
	p=(char*)malloc(100);
}

void Test(void){
	char *str=NULL;
	GetMemory(str);
	strcpy(str,"hello world");  //出错
	printf(str);
}
36.程序查错–“野指针”用于变量值的互换
void swap(int *p1,int *p2){
	int *p;             //没有申请指向空间 运行会导致程序崩溃
	*p=*p1;
	*p1=*p2;
	*p2=*p;
}

应该改为:

void swap(int *p1,int *p2){
	int p;
	p=*p1;
	*p1=*p2;
	*p2=p;
}
全局变量和局部变量重名
#include <iostream>

using namespace std;

int i=2;

int main(){
	int a=i;
	int i=3;;
	cout<<a<<endl;   //2
	cout<<i<<endl;   //3
	system("pause");
}
37.内存的分配方式有几种

解析:

1.从静态存储区域分配内存。程序编译的时候内存已经分配好了,并且在程序的整个运行期间都存在,例如全局变量。

2.在栈上创建。在执行函数时,函数内部局部变量的存储单元可以在栈上创建,函数结束时这些存储单元自动被释放。处理器的指定集中有关于栈内存的分配运算,因此效率很高,但是分配的内存容量有限。

3.从堆上分配内存,亦称为动态内存分配。程序在运行的时候用malloc函数或new运算符申请任意大小的内存,程序员要用free函数或delete运算符释放内存。动态内存使用非常灵活,但问题也很多。

Search

    Post Directory