C++中的内存管理

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏来自地球男人的部落格

[LeetCode] 80. Remove Duplicates from Sorted Array II

【原题】 Follow up for “Remove Duplicates”: What if duplicates are allowed at ...

22290
来自专栏Python数据科学

99%的人都不知道的pandas骚操作(一)

pandas有一种功能非常强大的方法,它就是accessor,可以将它理解为一种属性接口,通过它可以获得额外的方法。其实这样说还是很笼统,下面我们通过代码和实例...

48520
来自专栏吴伟祥

编码总结笔记 原

我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一...

13460
来自专栏hbbliyong

C#基础知识回顾---你不知道的Lazy<T>

    对象的创建方式,始终代表了软件工业的生产力方向,代表了先进软件技术发展的方向,也代表了广大程序开发者的集体智慧。以new的方式创建,通过工厂方法,利用I...

28230
来自专栏magicsoar

关于字符编码的那些事

一、编码是什么 编码为了某种目的把信息从一种形式集合转换为另一种形式集合的过程,古时的鸣金收兵,从某种意义上讲也是一种编码,将帅发出了退兵的命令,为了让更多的人...

20560
来自专栏分布式系统和大数据处理

C#中的泛型

.Net 1.1版本最受诟病的一个缺陷就是没有提供对泛型的支持。通过使用泛型,我们可以极大地提高代码的重用度,同时还可以获得强类型的支持,避免了隐式的装箱、拆箱...

10070
来自专栏xiaoxi666的专栏

Kolakoski序列产生器

10120
来自专栏CDA数据分析师

那些容易被忽略的Python编程方式

Python 之禅 The Zen of Python, by Tim Peters Beautiful is better than ugly. 优美胜于丑陋...

218100
来自专栏Play & Scala 技术分享

挑逗 Java 程序员的那些 Scala 绝技

有个问题一直困扰着 Scala 社区,为什么一些 Java 开发者将 Scala 捧到了天上,认为它是来自上帝之吻的完美语言;而另外一些 Java 开发者却对它...

18360
来自专栏Java爬坑系列

【Java入门提高篇】Day1 抽象类

  基础部分内容差不多讲解完了,今天开始进入Java提高篇部分,这部分内容会比之前的内容复杂很多,希望大家做好心理准备,看不懂的部分可以多看两遍,仍不理解的部分...

23260

扫码关注云+社区

领取腾讯云代金券