zoukankan      html  css  js  c++  java
  • C/C++动态内存管理以及虚函数

    C/C++动态内存管理

    C语言动态内存管理
    申请内存的方式

    栈上(静态内存管理)
    1.生命周期随栈帧。栈帧结束,内存归还给操作系统,无需程序猿管理。

    2.空间开辟的大小固定,申请数组时数组的大小必须指定。他内存在编译时期就已经分配好。

    3.程序在运行时期不能进行内存申请。而这种情况在编程中又很常见。所以就需要动态内存管理。

    堆上(动态内存管理)
    1.生命周期由程序猿管理。需要手动申请手动释放。且必须释放,否则就会造成内存泄露

    2.开辟空间大小由程序猿指定,更灵活。空间分配在程序运行期间分配。

    对比:栈上申请内存比较省心,规规矩矩。缺乏灵活性,而堆上申请内存更为灵活。但是灵活也就意味着风险。如果只申请,不释放,就会造成内存泄露。释放的内存的申请的内存要匹配。   

      
      int
    *p = (int *)malloc(20*sizeof(int)); int *pp = (int *)calloc(20, sizeof(int)); int i; printf("malloc申请的空间值: "); for ( i=0 ; i < 20; i++) { printf("%d ", *p++); } printf(" "); printf("calloc申请的空间的值: "); for ( i=0 ; i < 20; i++) { printf("%d ", *pp++); }   free(p);   free(pp);
    class Array
    {
        public:
            Array(size_t size=10)
                :_size(size)
                ,_a(0)
        {
            cout<<"Array(size_t size)"<<endl;
            if(size>0)
            {
                _a=new int[size];
            }
        }
            ~Array()
            {
                cout<<"~Array()"<<endl;
                if(_a)
                {
                    delete[]_a;
                    _a=0;
                    _size=0;
                }
    
            }
        private:
            int * _a;
            size_t _size;
    };
    int main()
    {
        Array* p1=new Array;
        delete p1;
        Array* p2=new Array[5];
        delete []p2;
        return 0;
    
    }

    C++杂谈 为什么需要虚析构函数

    ①虚函数:在类的成员函数前面加virtual关键字的函数;
    一般把虚函数定义在public区,方便在主函数中调用
    如果一个类有一个虚函数,则该类就有一个虚函数列表,所有该类的对象都共享这个虚函数表;(QT调试过程中显示的是vptr)
    如果一个类有一个或者一个以上的虚函数,则该类有且只有一张虚函数表,每个类都只有一个虚函数表,该类的所有对象都共享这张虚函数表
    子类的虚函数表中子类的虚函数覆盖父类的虚函数的情况,当子类将父类的虚函数override时,就覆盖了父类的虚函数;

    满足override的条件:函数名相同,函数的返回值相同,形参列表相同;

    纯虚函数:形式为 virtual void fun1() = 0
    纯虚函数不需要实现,原因是不会被调用到;

    抽象基类:至少有一个纯虚函数的类;
    抽象基类不能产生该类的对象,但可以有该类的指针或引用;
    在子类中必须将父类的纯虚函数实现,不然该子类也是抽象基类;

    当一个类有子类时,该类的析构函数必须是虚函数,原因:会有资源释放不完全的情况;

    对象销毁时只调用了父类的析构函数。如果这时子类的析构函数中有关于内存释放的操作,将会造成内存泄露。所以需要给父类的析构函数加上virtual。

    刚开始的时候对于这个问题我一直搞不明白,总觉得这是多此一举,后来上网查资料看到了一些人的解释明白了为什么要这样,用一个例子来解释应该最好理解了:

    你写了一个飞机游戏,画面里出现什么类型飞机是随机决定的,你的代码里也就不可能用一个具体飞机类型来操作。 所以,往往是随机生成各种类型飞机,他们有共同的父类,你的代码就可以用父类指针来控制行为。比如中弹后的能量损失多少之类,每种飞机可能不同。

     

  • 相关阅读:
    TypeError: Iterator operand 0 dtype could not be cast from dtype('<M8[us]') to dtype('<M8[D]') according to the rule 'safe'
    Linux中matplotlib 中文显示问题解决
    自己动手实现爬虫scrapy框架思路汇总
    机器学习算法之多项式回归
    scrapy爬虫--苏宁图书
    Mongodb数据库基本操作
    day04 Python
    day03 Python爬虫
    day02 Python完结
    day01 python基础
  • 原文地址:https://www.cnblogs.com/mathyk/p/12118741.html
Copyright © 2011-2022 走看看