C++中的内存管理

        在C++中也是少不了对内存的管理,在C++中只要有new的地方,在写代码的时候都要想着delete。 new分配的时堆内存,在函数结束的时候不会自动释放,若是不delete我分配的堆内存,则会形成内存泄露。因此咱们要学会内存管理,不要内存泄露。在C++中的内存管理机制和OC中的还不太同样,在OC中的ARC机制会给程序员的内存管理省很多事,但在C++中没有ARC因此咱们要本身管理好本身开辟的内存。Java中也有本身相应的内存管理机制,好比JDBC里的获取的各类资源在finally里进行close等程序员

        那么什么状况下咱们写的程序会出现内存泄露呢?下面咱们将会举一个简单的例子来分析一下C++中的内存管理机制。函数

        1.创建一个测试类TestClass, TestClass类中有一个私有的属性(指针类型),有一个无惨的构造函数,有一个析构函数,还有一个display方法用于输出对象的信息测试

            测试类的声明以下:this

1
2
3
4
5
6
7
8
9
10
11
12
13
//内存管理的测试类
class  TestClass
{
private :
     char  *name;
public :
     //无参构造函数
     TestClass();
     //析构函数
     ~TestClass();
     //描述方法
     void  display();
};

      在xxx.cpp文件中定义类的实现方法spa

        实现构造方法,实现构造方法时要给属性指针分配空间,否则的话属性指针没有分配内存地址,调用时程序会崩溃,用new方法进行堆分配指针

1
2
3
4
5
6
7
8
9
//无参构造函数
TestClass::TestClass()
{
     cout <<  "TestClass()"  <<endl;
     //给指针属性分配内存(堆分配)
     this ->name =  new  char [255];
     //进行初始化
     strcpy ( this ->name,  "ludashi" );
}

        实现析构函数在析构函数中要对构造函数中堆分配的内存进行delete,否则会形成内存泄露code

1
2
3
4
5
6
//析构函数
TestClass::~TestClass()
{
     delete  []  this ->name;
     cout <<  "~TestClass()"  << endl;
}

         实现display函数,进行name的打印测试对象

1
2
3
4
5
//描述方法
void  TestClass::display()
{
     cout <<  this ->name <<endl;
}

        2. 在main函数中进行测试内存

        实例化对象时进行堆分配:须要手动进行内存的释放,否则也会形成内存的泄露ci

1
2
//TestClass类的初始化,堆分配,须要delete
TestClass * testClass =  new  TestClass();

        实例化对象的栈分配:不须要手动释放内存,大括号结束时就自动释放栈内存

1
2
//栈分配,不用delete,出大括号后自动释放
  TestClass stackClass = TestClass()

        信息的打印输出

1
testClass->display();

        调用delete来释放堆分配的对象

1
delete  testClass;

        3.程序运行结果:若是不加delete testClass; 析构函数只会调用一个,由于堆分配的对象不会自动释放,须要手动释放,不加则会形成内存的泄露

1
2
3
4
5
TestClass()
TestClass()
ludashi
~TestClass()
~TestClass()

    4.拷贝构造函数

        若是在main函数中加入下面这句话,程序在运行时就会崩掉,若是要想程序正常运行能够把析构函数中的delete [] this->name;注释掉就能够运行。不过这样会引发内存的泄露。那么咱们来研究一下为何加上下面这句话程序会崩掉呢?缘由是下那句话的意思是copyTest和stackClass指向同一块栈内存,当其中一个调用析构函数时就会把name给delete掉,另外一个在析构调用delete时就会报错。怎么从基本上解决问题呢?接下来就是拷贝构造函数出场的时候啦。

1
TestClass copyTest = stackClass;

        下面是拷贝构造函数的定义方法

1
2
3
4
5
6
7
8
//拷贝构造函数
TestClass::TestClass( const  TestClass &test)
{
     //在堆中分配新的内存
     this ->name =  new  char [255];
     //进行拷贝
     strcpy ( this ->name, test.name);
}

    在main函数中调用拷贝构造函数 ,这样的代码有不会有刚才的问题了

1
TestClass copyTest = stackClass;

    5.再提内存管理,不由又想到初学C++那会的一句话“先构造的后析构”;有new的地方就得想着delete,为了不内存泄露。 

    ​    ​上面的拷贝构造函数的做用是在声明对象的时候能够利用拷贝构造函数给新的对象赋值,若是像下面的这种状况就会出现过分释放的问题;  ​    

1
2
3
TestClass  test1 = TestClass();
TestClass  test2 = TestClass();
test2 = test1;

    ​    ​接下来就该操做符重载出场的时候了(operator = )把=号进行重载

1
2
3
4
5
6
//对象之间的赋值:操做符重载
TestClass & TestClass :: operator = ( const  TestClass &test)
{
     strcpy ( this ->name, test.name);
     return  * this ;
}
相关文章
相关标签/搜索