C++内存管理2-内存泄漏

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

  假设我们要开发一个String类,它可以方便地处理字符串数据。我们可以在类中声明一个数组,考虑到有时候字符串极长,我们可以把数组大小设为200,但一般的情况下又不需要这么多的空间,这样是浪费了内存。对了,我们可以使用new操作符,这样是十分灵活的,但在类中就会出现许多意想不到的问题,本文就是针对这一现象而写的。现在,我们先来开发一个String类,但它是一个不完善的类。的确,我们要刻意地使它出现各种各样的问题,这样才好对症下药。好了,我们开始吧!

                        /* String.h */

#ifndef STRING_H_

#define STRING_H_

class String

{

private:

char * str; //存储数据

int len; //字符串长度

public:

String(const char * s); //构造函数

String(); // 默认构造函数

~String(); // 析构函数

注意:没有赋值构造函数
friend ostream & operator<<(ostream & os,const String& st); }; #endif                         /*String.cpp*/ #include <iostream> #include <cstring> #include "String.h" using namespace std; String::String(const char * s) { len = strlen(s); str = new char[len + 1]; strcpy(str, s); }//拷贝数据 String::String() { len =0; str = new char[len+1]; str[0]='"0'; } String::~String() { cout<<"这个字符串将被删除:"<<str<<'"n';//为了方便观察结果,特留此行代码。 delete [] str; } ostream & operator<<(ostream & os, const String & st) { os << st.str; return os; }                       /*test_right.cpp*/ #include <iostream> #include <stdlib.h> #include "String.h" using namespace std; int main() { String temp("天极网"); cout<<temp<<'"n'; system("PAUSE"); return 0; }

  运行结果:

 天极网

  请按任意键继续. . .

大家可以看到,以上程序十分正确,而且也是十分有用的。可是,我们不能被表面现象所迷惑!下面,请大家用test_String.cpp文件替换test_right.cpp文件进行编译,看看结果。有的编译器可能就是根本不能进行编译

#include <iostream>

#include <stdlib.h>

#include "String.h"

using namespace std;

void show_right(const String&);

void show_String(const String);//注意,参数非引用,而是按值传递。

int main()

{

String test1("第一个范例。");

String test2("第二个范例。");

String test3("第三个范例。");

String test4("第四个范例。");

cout<<"下面分别输入三个范例:"n";

cout<<test1<<endl;

cout<<test2<<endl;

cout<<test3<<endl;

String* String1=new String(test1);//复制构造函数测试

cout<<*String1<<endl;

delete String1;

cout<<test1<<endl; //在Dev-cpp上没有任何反应。

cout<<"使用正确的函数:"<<endl;

show_right(test2);//地址传递,参数测试

cout<<test2<<endl;

cout<<"使用错误的函数:"<<endl;

show_String(test2);//赋值参数传递测试

cout<<test2<<endl; //这一段代码出现严重的错误!

String String2(test3);//复制构造函数测试

cout<<"String2: "<<String2<<endl;

String String3;

String3=test4;//赋值测试

cout<<"String3: "<<String3<<endl;

cout<<"下面,程序结束,析构函数将被调用。"<<endl;

return 0;

}

void show_right(const String& a)

{

cout<<a<<endl;

}

void show_String(const String a)

{

cout<<a<<endl;

}

运行结果:

下面分别输入三个范例:

  第一个范例。

  第二个范例。

  第三个范例。

  第一个范例。

  这个字符串将被删除:第一个范例。

  使用正确的函数:

  

  第二个范例。

  第二个范例。

  使用错误的函数:

  第二个范例。

  这个字符串将被删除:第二个范例。

  这个字符串将被删除:?=

  ?=

  String2: 第三个范例。

  String3: 第四个范例。

  下面,程序结束,析构函数将被调用。

  这个字符串将被删除:第四个范例。

  这个字符串将被删除:第三个范例。

  这个字符串将被删除:?=

  这个字符串将被删除:x =

  这个字符串将被删除:?=

  这个字符串将被删除:

  现在,请大家自己试试运行结果,或许会更加惨不忍睹呢!下面,我为大家一一分析原因。

  首先,大家要知道,C++类有以下这些极为重要的函数:

一:复制构造函数。

二:赋值函数。

  我们先来讲复制构造函数。什么是复制构造函数呢?比如,我们可以写下这样的代码:String test1(test2);这是进行初始化。我们知道,初始化对象要用构造函数。可这儿呢?按理说,应该有声明为这样的构造函数:String(const String &);可是,我们并没有定义这个构造函数呀?答案是,C++提供了默认的复制构造函数,问题也就出在这儿。

(1):When,什么时候会调用复制构造函数呢?(以String类为例。)

  在我们提供这样的代码:String test1(test2)时,它会被调用;当函数的参数列表为按值传递,也就是没有用引用和指针作为类型时,将会被以赋值构造函数调用。

  如:void show_String(const String),它会被调用。其实,还有一些情况,但在这儿就不列举了。

(2):What,它是什么样的函数。

  它的作用就是把两个类进行复制。

  拿String类为例,C++提供则可以为这样的类,提供如下的默认复制构造函数是这样的:

  即:默认完成对所有类成员的赋值操作。

String(const String& a)

{

  str=a.str;

  len=a.len;

}

endl;

参考博客:

  https://www.cnblogs.com/findumars/p/5929831.html

猜你喜欢

转载自www.cnblogs.com/icmzn/p/11821870.html