博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++中的内存管理
阅读量:7028 次
发布时间:2019-06-28

本文共 2413 字,大约阅读时间需要 8 分钟。

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

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

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

            测试类的声明如下:

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文件中定义类的实现方法

        实现构造方法,实现构造方法时要给属性指针分配空间,不然的话属性指针没有分配内存地址,调用时程序会崩溃,用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,不然会造成内存泄露

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函数中进行测试

        实例化对象时进行堆分配:需要手动进行内存的释放,不然也会造成内存的泄露

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
;
}

转载地址:http://jnrxl.baihongyu.com/

你可能感兴趣的文章
GitLab
查看>>
m6-第10周作业
查看>>
Salesforce Apex学习 : 利用Schema命名空间中的DescribeSObjectResult类型来获取sObject对象的基本信息...
查看>>
沃通SSL证书支持最新顶级域名
查看>>
网站建设流程图
查看>>
cc2540 usbdongle 安装驱动失败的终极解决方法 【原创,多图】
查看>>
STS(Eclipse)+Maven将war项目部署到远程的tomcat
查看>>
云虚机选购指南之一怎样选择一款适合自己的云虚拟主机
查看>>
信息技术手册查重错误比对分析程序开发记录2
查看>>
ulimit 命令详解
查看>>
UML系列:前序:序列图
查看>>
BW Query设计中公式冲突解决方案
查看>>
简单Linux C线程池2
查看>>
2011-09-21 16:53 VS2010、C#、Emgu CV配置 ; 在C#下使用OpenCV ; C#中使用OpenCV(Emgu CV);...
查看>>
mysql索引测试案例
查看>>
从topcoder赚钱的方法~
查看>>
会计电算化模拟试题9
查看>>
一名大学生在银行工作8年的职场感悟
查看>>
阻带窗函数[数字信号处理]使用窗函数设计FIR滤波器
查看>>
客户端生成nginx webdav配置
查看>>