您好,欢迎来到欧得旅游网。
搜索
您的当前位置:首页C++内存管理学习内存泄漏 电脑资料

C++内存管理学习内存泄漏 电脑资料

来源:欧得旅游网
C++内存管理学习内存泄漏 电脑资料

3 内存泄漏-Memory leak

3.1 C++中动态内存分配引发问题的解决方案

假设我们要开发一个String类,它可以方便地处理字符串数据, 下面上例子, 1: /* String.h */ 2: #ifndef STRINGH 3: #define STRINGH 4:

5: class String 6: {

7: private:

8: char * str; //存储数据 9: int len; //字符串长度 10: public:

11: String(const char * s); //构造函数 12: String(); // 默认构造函数 13: ~String(); // 析构函数

14: friend ostream & operator<<(ostream & os,const String& st); 15: }; 16: #endif 17:

18: /*String.cpp*/ 19: #include

20: #include

21: #include \"String.h\" 22: using namespace std;

23: String::String(const char * s) 24: {

25: len = strlen(s);

26: str = new char[len + 1]; 27: strcpy(str, s); 28: }//拷贝数据 29: String::String() 30: { 31: len =0;

32: str = new char[len+1]; 33: str[0]='\"0'; 34: }

35: String::~String() 36: {

37: cout<<\"这个字符串将被删除:\"< 38: delete [] str; 39: }

40: ostream & operator<<(ostream & os, const String & st) 41: { 42: os<

43: return os; 44: }

45:

46: /*testright.cpp*/ 47: #include 48: #include

49: #include \"String.h\" 50: using namespace std; 51: int main() 52: {

53: String temp(\"String类的不完整实现,用于后续内容讲解\"); 54: cout<

55: system(\"PAUSE\"); 56: return 0; 57: }

运行结果(运行环境Dev-cpp)如下列图所示,外表看上去程序运行很正确,到达了自己程序运行的目的,但是,不要被外表结果所迷惑!

1: #include 2: #include

3: #include \"String.h\" 4: using namespace std; 5:

6: void showright(const String& a) 7: { 8: cout< 9: }

10: void showString(const String a) //注意,参数非引用,而是按值传递。 11: { 12: cout< 13: } 14:

15: int main() 16: {

17: String test1(\"第一个范例, 18: String test2(\"第二个范例。\"); 19: String test3(\"第三个范例。\"); 20: String test4(\"第四个范例。\"); 21: cout<<\"下面分别输入三个范例\"< 22: cout< 23: cout< 24: cout< 25:

26: String* String1=new String(test1); 27: cout<<*String1< 28: delete String1; 29: cout< 30:

31: cout<<\"使用正确的函数:\"< 32: showright(test2); 33: cout<

34: cout<<\"使用错误的函数:\"< 35: showString(test2); 36: cout< 37:

38: String String2(test3); 39: cout<<\"String2: \"< 40:

41: String String3; 42: String3=test4; 43: cout<<\"String3: \"<

44: cout<<\"下面,程序完毕,析构函数将被调用。\"< 45:

46: return 0; 47: }

运行结果(环境Dev-cpp):程序运行最后崩溃!!!到这里就看出来上面的String类存在问题了吧。(读者可以自己运行一下看看,可以换vc或者vs等等试试)

通过查看,原来主要是复制构造函数和赋值操作符的问题,读者可能会有疑问,这两个函数是什么,怎会影响程序呢。接下来笔者慢慢结识。

首先,什么是复制构造函数和赋值操作符?------>限于篇幅,详细分析请看《c++中复制控制详解(copy control)》 Tip:复制构造函数和赋值操作符 (1)复制构造函数(copy constructor)

复制构造函数(有时也称为:拷贝构造函数)是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用.当定义一个新对象并用一个同类型的对象对它进展初始化时,将显示使用复制构造函数.当将该类型的对象传递给函数或者从函数返回该类型的对象时,将隐式使用复制构造函数。 复制构造函数用在:

对象创立时使用其他相同类型的对象初始化; 复制对象作为函数的参数进展值传递时; 复制对象以值传递的方式从函数返回。

一般情况下,编译器会给我们自动产生一个拷贝构造函数,这就是“默认拷贝构造函数”,这个构造函数很简单,仅仅使用“老对象”的数据成员的值对“新对象”的数据成员一一进展赋值。使用默认的复制构造函数是叫做浅拷贝。

相对应与浅拷贝,那么有必要有深拷贝(deep copy),对于对象中动态成员,就不能仅仅简单地赋值了,而应该有重新动态分配空间。

如果对象中没有指针去动态申请内存,使用默认的复制构造函数就可以了,因为,默认的复制构造、默认的赋值操作和默认的析构函数能够完成相应的工作,不需要去重写自己的实现。否那么,必须重载复制构造函数,相应的也需要重写赋值操作以及析构函数。 2.赋值操作符(The Assignment Operator)

一般而言,如果类需要复制构造函数,那么也会需要重载赋值操作符。首先,了解一下重载操作符。重载操作符是一些函数,其名字为operator后跟所定义的操作符符号,因此,可以通过定义名为operator=的函数,进展重载赋值定义。操作符函数有一个返回值和

一个形参表。形参表必须具有和该操作数数目相同的形参。赋值是二元运算,所以该操作符有两个形参:第一个形参对应的左操作数,第二个形参对应右操作数。

赋值和赋值一般在一起使用,可将这两个看作一个单元,如果需要其中一个,几乎也肯定需要另一个。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- ovod.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务