盒子
盒子

C++申请动态空间问题

###C++ 申请动态空间的一点总结

1.内存中的堆和栈

关于 ,最通俗易懂的区别就是:栈是编译器自动申请的,而堆是人为申请的。 此外,栈的空间在程序结束的时候由系统或者编译器自动释放,而堆则在程序结束前由程序员手动使用delete释放,或者忘记手动释放,由系统在程序结束的时候自动回收。
看一个例子

char *A=new char[10]

这里地址(*A)就是存放在栈中,而new申请的十个字符空间则是在堆中。

内存的分配如图所示:

1

2.c++中的new关键字

malloc (memory allocation,中文叫动态内存分配)可以申请动态内存,是C/C++语言的标准库函数,可以在C和C++中使用。与之相对应的就是new了,new是C++中的关键字,只能在C++中使用。两者的区别与联系在于

  • malloc和new申请内存中的堆,得到的是指向该堆的指针,不需要使用时记得要释放,释放后把指向这块内存的指针指向NULL,防止后面的程序不小心使用它,malloc和free配合使用,new和delete配合使用。
  • malloc只管分配内存,不会对其进行初始化,这是与new的最大区别。new相当于在malloc的基础上再加一个构造函数。
  • new表达式返回指向该新创建对象的指针,我们可以通过指针来访问此对象。malloc分配成功则返回指向被分配内存的指针。
  • new返回指定类型的指针,并且可以自动计算所需要大小。malloc 则必须要由我们计算字节数,并且在返回后强行转换为实际类型的指针。
1
2
3
4
int *p;   
p = new int; //分配大小为sizeof(int)
int* parr;   
parr = new int [100]; //分配大小为sizeof(int)*100
1
2
int* p;   
p = (int *) malloc (sizeof(int)*128); //分配128个整形存储单元,并将首地址放在p中。

new相比malloc的优势:对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

new使用的一些注意点:

  • new申请的虽然是一个动态空间,但返回的是一个指针,指向申请空间的第一个位置的地址,对于指针的访问,C++一般没啥限制,都靠自己把我是否越界,所以一般你装了杀毒软件,运行时可能会提示为杀毒软件。
  • 程序员需要对申请的内存负责,new和delete成对出现,new了就需要delete。内存是分配在进程的虚拟地址空间里面的。所以程序退出,内存也会释放

最近给本科生批作业,一项很耗时的任务,但也还是很有收获的。从老师的角度看学生,其实看得还是很清楚的,哪些学生喜欢思考,做事踏实,哪些学生有些浮躁,应付了事,这些结论不再是主观得出的,而是通过足够的信息(这里的话就是他们的代码),究竟有怎样风格的代码,很大程度上就反应了他究竟是一个怎样态度的学生,想起当初自己是那个年纪的样子,迷迷糊糊的,根本不怎么懂得思考以及改进。其实就是缺少观察事物的角度,不同角色的体验。当然这对现在的我也还是有些许帮助的。

——————————————分割线—————————————-

给一个例子来反映下需要思考的重要性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# include <iostream>
using namespace std;
class Person
{
public:
Person(char *pname="noname", int pid = 100)
{
cout<< "Call constructor." <<endl;
name = new char[strlen(pname)+1]; //new申请空间
name = pname;
id = pid;
}
Person( Person &p )
{
cout << "Call copy constructor." << endl;
name = new char[strlen(p.name)+1];
name = p.name;
id = p.id;
}
~Person()
{
cout<<"Call destructor."<<endl;
delete []name;
}
void printinfo()
{
cout << name << "," << id << endl;
}
private:
char *name;
int id;
};
int main()
{
Person wang("wang",101);
wang.printinfo();
Person li(wang);
li.printinfo();
return 0;
}

这里new申请了空间,返回动态空间的第一个位置的指针给name,但又紧接着把P.name的指针赋给了name,也就是说动态空间白申请了,虽然程序最后也能正确运行,犯这个错误的原因就是对指针的理解不够清晰,正确的做法应该是利用strcpy()进行复制。还有一个错误就是没有对申请的动态空间是否申请成功进行判断。所以,平常编程出错了,不要急着修改成正确的答案,要仔细思考下出错的原因。

参考

http://www.cnblogs.com/fly1988happy/archive/2012/04/26/2470542.html