2017C++基础——网课笔记(40到45)

四十. 构造函数的初始化列表1
#include <iostream>

using namespace std;

class A
{
public:
    A(int a)
    {
        cout<<"A()..."<<endl;
        m_a = a;
    }

    ~A()
    {
        cout<<"~A()..."<<endl;
    }

    void printA()
    {
        cout<<"a = "<<m_a<<endl;
    }
private:
    int m_a;
};

class B
{
public:
    B(A& a1, A& a2, int b): m_a1(a1),m_a2(a2)
    {
        m_b = b;
    }

    void printB()
    {
        cout<<"b= "<< m_b <<endl;
        m_a1.printA();
        m_a2.printA();
    }

    ~B()
    {
        cout<<"~B()..."<<endl;
    }

private:
    int m_b;
    A m_a1;
    A m_a2;
};
int main()
{
    A a1(10),a2(100);

    B b(a1,a2,1000);
    b.printB();
    return 0;
}

四十一. 构造函数的初始化列表2(略)

四十二.强化练习1
#include <iostream>
#include <stdio.h>
using namespace std;

class ABCD
{
public:
    ABCD(int a, int b, int c)
    {
        _a = a;
        _b = b;
        _c = c;
        printf("ABCD() construct, a:%d, b:%d, c:%d \n",_a,_b,_c);
    }

    ~ABCD()
    {
        printf("ABCD() destruct, a:%d, b:%d, c:%d \n",_a,_b,_c);
    }

    int getA()
    {
        return _a;
    }
private:
    int _a;
    int _b;
    int _c;
};

class MyE
{
public:
    MyE(): abcd1(1,2,3), abcd2(4,5,6),m(100)
    {
        cout<<"MyD().."<<endl;
    }

    ~MyE()
    {
        cout<<"~MyE()..."<<endl;
    }

    MyE(const MyE& obj):abcd1(7,8,9), abcd2(10,11,12),m(100)
    {
        cout<<"MyE(const MyE& obj)"<<endl;
    }

public:
    ABCD abcd1;
    ABCD abcd2;
    const int m;
};

int doThing(MyE mye1)
{
    cout<<"doThing() mye1.abc1.a:"<<mye1.abcd1.getA()<<endl;
    return 0;
}

int run()
{
    MyE myE;
    doThing(myE);
    return 0;
}

int run2()
{
    cout<<"run2() starts...."<<endl;
    ABCD(400,500,600);
    cout<<"run2() ends...."<<endl;
    return 0;
}

int main()
{
    run2();
    return 0;
}


四十三.强化练习2
#include <iostream>

using namespace std;

class MyTest
{
public:
    MyTest(int a, int b, int c)
    {
        _a = a;
        _b = b;
        _c = c;
    }

    MyTest(int a, int b)
    {
        _a = a;
        _b = b;
        MyTest(a,b,100); //产生新的匿名对象
    }

    ~MyTest()
    {
        cout<<"~Mytest:"<<_a<<", "<<_b<<", "<<_c<<endl;
    }

    int getC()
    {
        return _c;
    }

    void setC(int val)
    {
        _c = val;
    }
private:
    int _a;
    int _b;
    int _c;


};
int main()
{
    MyTest t1(20,30);
    return 0;
}

四十四.new和delete1
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;

//c语言中
void test1()
{
    int *p = (int*)malloc(sizeof(int));
    *p = 10;
    if(p != NULL)
    {
        free(p);
        p = NULL;
    }

    int * array_p = (int*) malloc(sizeof(int) *10);

    for(int i = 0; i<10; i++)
    {
        array_p[i] = i +1;
    }

    for(int i = 0;i<10;i++)
    {
        printf("%d",array_p[i]);
    }

}

//c++中
void test2()
{
    int * p = new int;
    *p = 10;
    if(p != NULL)
    {
        delete p;
        p = NULL;
    }

    int *array_p = new int[10];

    for(int i = 0; i<10; i++)
    {
        array_p[i] = i +1;
    }

    for(int i = 0;i<10;i++)
    {
        cout<< array_p[i]<<" ";
    }

    cout<<endl;

    if(array_p != NULL)
    {
        delete [] array_p;
    }
}

int main()
{
    test1();

    cout<<endl<<"---------------------------"<<endl;

    test2();

    return 0;
}

四十五.new和delete2

这里,我们必须对《new与malloc》,《delete与free》这两组关系有比较清晰的认识


delete tp释放的是tp本身,而析构函数,是用来析构new出来的空间。

delete也是类似,delete会做的事,事先去触发析构函数,再去销毁对象。而与此同时,free本身,只是去销毁对象,释放空间。它缺了delete的第一步。

2. 基于上述原因,我们需要掌握delete与delete[]之间的区别
(1)基本数据类型分配和回收空间

针对内置类型(即基本数据类型)使用new分配后的不管是数组还是非数组形式内存空间用两种方式均可,如:

int *a = new int[10];
delete a;//正确
<=>等价于
delete[] a;//正确

代码示例:


#include <iostream>;

using namespace std;
int main()
{
    int NUM = 3;

    int *a1 = new int[NUM];
    cout<<a1<<endl;
    delete a1;
    cout<<"释放了a1的空间"<<endl;

    int *a2 = new int[NUM];
    cout<<a2<<endl;
    delete[] a2;
    cout<<"释放了a2的空间"<<endl;

    system("pause");
    return 0;
}
=>01294750
  释放了a1的空间
  01294750
  释放了a2的空间
注:此种情况中的释放效果相同,原因在于:分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数。
它直接通过指针可以获取实际分配的内存空间,哪怕是一个数组内存空间(在分配过程中系统会记录分配内存的大小等信息,此信息保存在结构体_CrtMemBlockHeader中,具体情况可参看VC安装目录下CRT\SRC\DBGDEL.cpp)
(2)自定义类型分配和回收空间(即对象数组的内存管理)
  • 针对自定义类型使用new分配后的空间,若是数组形式的内存空间,两种方式效果截然不同,如:

    T *a = new T[10];
    delete a;//错误,仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数,剩下的从a[1]到a[9]这9个用户自行分配的对应内存空间将不能释放 从而造成内存泄漏。
    <!=>效果截然不同
    delete[] a;//正确,调用使用类对象的析构函数释放用户自己分配内存空间并且释放了a指针指向的全部内存空间

  • 错误程序示例:

    
    #include <iostream>;
    
    using namespace std;
    class T 
    {
    public:
        T() 
        {
            cout <<"构造T"<<endl;
        }
        ~T() 
        {
            cout <<"析构T"<<endl;
        }
    };
    int main()
    {
        int NUM = 3;
    
        T *p1 = new T[NUM];
        cout<<p1<<endl;
        delete p1;//错误释放语句
        cout<<"释放了p1空间"<<endl;
    
        T *p2 = new T[NUM];
        cout<<p2<<endl;
        delete[] p2;//正确释放语句
        cout<<"释放了p2空间"<<endl;
    
        system("pause");
        return 0;
    }
    =>构造T
      构造T
      构造T
      010F4754
      析构T
      程序崩溃了Debug Assertion Failed!
      Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 正确程序示例:

    
    #include <iostream>;
    
    using namespace std;
    class T 
    {
    public:
        T() 
        {
            cout <<"构造T"<<endl;
        }
        ~T() 
        {
            cout <<"析构T"<<endl;
        }
    };
    int main()
    {
        int NUM = 3;
    
        T *p1 = new T[NUM];
        cout<<p1<<endl;
        delete[] p1;//正确释放语句
        cout<<"释放了p1空间"<<endl;
    
        T *p2 = new T[NUM];
        cout<<p2<<endl;
        delete[] p2;//正确释放语句
        cout<<"释放了p2空间"<<endl;
    
        system("pause");
        return 0;
    }
    =>构造T
      构造T
      构造T
      1664754
      析构T
      析构T
      析构T
      释放了p1空间
      构造T
      构造T
      构造T
      1664754
      析构T
      析构T
      析构T
      释放了p2空间
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    注:在用这些类生成对象数组的时候,用delete[]来释放它们才是王道。

(3)总结,别管那么多,反正如果定义的事单个个体,就delete。
如果定义的是数组,就delete[],这样绝对不会出错
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值