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

C++中的内存管理的更多相关文章

  1. Unity游戏开发中的内存管理_资料

    内存是手游的硬伤——Unity游戏Mono内存管理及泄漏http://wetest.qq.com/lab/view/135.html 深入浅出再谈Unity内存泄漏http://wetest.qq.c ...

  2. cocos2dx中的内存管理机制及引用计数

    1.内存管理的两大策略: 谁申请,谁释放原则(类似于,谁污染了内存,最后由谁来清理内存)--------->适用于过程性函数 引用计数原则(创建时,引用数为1,每引用一次,计数加1,调用结束时, ...

  3. Cocos2d-x开发中C++内存管理

    由于开始并没有介绍C++语言,C++的内存管理当然也没进行任何的说明,为了掌握Cocos2d-x中的内存管理机制,是有必要先了解一些C++内存管理的知识.C++内存管理非常复杂,如果完全地系统地介绍可 ...

  4. 6.关于QT中的内存管理,动态的制作,动态库的调用,静态库的制作

     一  QT的内存管理 1  QT中的内存管理是QObject来管理的 2  QT中的内存管理没有cocos2dx中的引用计数 3  组件能够指定父对象 QTimer *timer = QTime ...

  5. C语言中的内存管理

    开始陆续的发一下唐老师视频的笔记吧,顺便带一些正冲哥书的的内容.不能一下都发出来,因为内容发多了自己也受不了,而且发的都是学习视频时候的一些笔记,可能会有一些问题不是很清晰. 先说一下C语言中的内存管 ...

  6. JNI中的内存管理(转)

    源:JNI中的内存管理 JNI 编程简介 JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互 ...

  7. javascript中的内存管理和垃圾回收

    前面的话 不管什么程序语言,内存生命周期基本是一致的:首先,分配需要的内存:然后,使用分配到的内存:最后,释放其内存.而对于第三个步骤,何时释放内存及释放哪些变量的内存,则需要使用垃圾回收机制.本文将 ...

  8. php中的内存管理的介绍(转)

    本篇文章给大家带来的内容是关于php中的内存管理的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 一.php内存管理概述——Zend引擎 由于计算机的内存由操作系统进行管理,所以 ...

  9. Android中的内存管理机制以及正确的使用方式

    概述 从操作系统的角度来说,内存就是一块数据存储区域,属于可被操作系统调度的资源.现代多任务(进程)的操作系统中,内存管理尤为重要,操作系统需要为每一个进程合理的分配内存资源,所以可以从两方面来理解操 ...

随机推荐

  1. HTML5 与 CSS3 jQuery部分知识总结【转】

    一.    HTML5 为什么需要HTML5 什么是HTML5 HTML5现状及浏览器支持 HTML5优点与缺点 HTML5语法规则与文档声明 HTML5新增表达标签 HTML5多媒体组件 HTML5 ...

  2. 【转】Android Studio-1.2版本设置教程

    如果重新安装Android Studio的话要重新配置风格选项啥的,这篇是个很好的教程,原文链接:http://blog.csdn.net/skykingf/article/details/45485 ...

  3. mysql不能插入中文

    mysql不能插入中文 解决办法: 1.打开终端,连接数据库  mysql -u root -p; 2.输入 satus; 查看状态 3.输入 set char set 'gbk'; 4.如果是已有的 ...

  4. C及C++中typedef的简单使用指南

    又是在学数据结构的时候,发现了之前学习的知识遗忘很多,在发现对C/C++中关键字typedef的理解还是没有到位后,我翻阅了学C++用到的课本,又问了度娘,也看了不少关于typedef用法的博客.于是 ...

  5. 移动端图片上传base64编码

    $base64 = "/9j/4AAQSkZJRgABAQEAkACQAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAA ...

  6. PHP基础知识之遍历

    遍历对象的时候,默认遍历对象的所有属性 class MyClass{    public $var1 = 'value 1';    public $var2 = 'value 2';    publ ...

  7. C#3.0扩展方法学习篇

     什么是类的扩展方法 扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. MSDN Extension methods enable you to &q ...

  8. sql 代码调试

    begin --开启事务 begin tran --插入 INSERT INTO [DICTIONARY] (TablName,Column_Id,Column_Name) --数据源 select ...

  9. for循环后面跟分号 - for (i = 0; i <= 3; i++);这不是错误语句

    #include<iostream> int main() { using namespace std; ; ; i <= ; i++); t = t + i; cout <& ...

  10. 升级为iOS9后,默认请求类型为https,如何使用http进行请求会报错(引用他人的)

    升级为iOS9后,默认请求类型为https,如何使用http进行请求会报错 The resource could not be loaded because the App Transport Sec ...