c语言的动态内存分配
在c语言中我们使用malloc/free函数
内存区域一般分为四部分:
全局变量、静态数据、常量======>>data area
所有类成员函数和非成员函数代码==>>code area
为运行函数而进行分配的局部变量、
函数参数、返回数据、返回地址等==>>stack area
动态内存分配区 ============>>heap area
C++的动态内存分配
在c++上使用运算符new/delete
在堆上生成对象,需要自动调用构造函数
在堆上生成的对象,在释放时需要自动调用析构函数
同样的,new/delete与malloc/free一样需要配对使用。同时,对象数组要用new[]/delete[]
生成和释放
下面用一个简单的例子来展示一下
我们看到,在上面的简单例子中,new Test() 调用了一次构造函数,delete调用了一次析构函数;malloc/free也一样。而new Test[2]应该是调用了两次构造函数,delete[2]调用了两次析构函数。运行结果如下:
通过比对结果和我们可以知道我们得到了正确的结论。
而如果在new []之后只调用了delete ,则会发生内存泄漏
动态内存分配
常量数据去存放常量数据,但常量数据不一定存放在常量常量数据去中,有些立即数直接和指令编码在一起,刚在代码区中。
字符串常量,编译器会去掉重复的字符串,保证只有一个副本。
常量是不能修改的。
字符串会被编译器自动放在常量数据区中,加const关键字修饰的全局变量也放在常量数据去中。
浅拷贝与深拷贝
对象的构造,也可以由拷贝构造函数完成,即用一个对象的内容去初始化另一个对象的内容。
此时,若对象使用了堆空间(注意和“堆对象”区分),就有深、浅拷贝的问题,不清楚则很容易出错。
1、什么是浅拷贝?
2、浅拷贝可能带来什么问题?
3、什么是深拷贝?
4、深拷贝的实现方法?
什么是浅拷贝
缺省拷贝构造函数:用一个对象的内容初始化另一个同类对象,也称为缺省的按成员拷贝,不是对整个类对象的按位拷贝。这种拷贝称为浅拷贝。
class String{
public:
String(const char* cstr);
String(const String& str);
String& operator= (const String& str);
~String();
char* get_c_str() const{return m_data;}
private:
char* m_data;
};类声明结束
浅拷贝带来的问题
int mian(){
String s1();
String s2("hello");
String s3(s1);
return 0; }//程序执行完,对象将被析构,此时出错。
析构时,如用缺省的析构函数,则动态分配的堆空
间不能回收。
如果用有“delete Name;”语句的析构函数,则先
析构s2时,堆空间已经释放,然后再析构s3
时出现了二次释放的问题。
这时就要重新定义拷贝构造函数,给每个对象独
立分配一个堆字符串,称深拷贝。
深拷贝——自定义拷贝构造
inline
String::String(const char* cstr)
{
if(cstr){
m_data= new char[strlen(cstr)+ 1];
strcpy(m_data,cstr);
}
else{
m_data = new char[1];
*m_data='\0' ;
}
}
inline
String& String::operator=(const String& str){
if(this==&str)return *this;
delete[] m_data;//释放字符串
m_data=new char[strlen(str.m_data)+ 1] ;//申请新内存
strcpy(m_data,str.m_data);
return *this;
}
堆内存是最常用的需要自定义拷贝构造函数的资源,但不是唯一的,如打开文件等也需要。
如果类需要析构函数来释放某些资源,则类也需要一个自定义的拷贝构造函数。此时,对象的拷贝就是深拷贝了。