c++构造和析构、new/delete

构造和析构的概念

  • 创建对象时,对象进行初始化的工作,就是构造
  • 销毁对象时,对对象进行清理工作,就是析构

创建对象和释放对象时,构造函数和析构函数自动调用,不需要人为调用

#include <iostream>
#include <string.h>
#include <string>
using namespace std;

class Person
{
public:
    // 构造函数 函数名和类名一致 没有返回值 不能写void 可以有参数 可以发生函数重载
    Person(int age, string name)
    {
        m_age = age;
        m_name = name;
    }
    // 析构函数 函数名:类名前加~  没有返回值 不可以有参数  不能发生函数重载
    ~Person()
    {
        cout <<"~~~~" <<endl;
    }

    int m_age;
    string m_name;
};

void test01()
{
    Person p1(10, "lucy");  // 构造函数是在实例化对象时会创建,就是在内存开辟空间时会被调用
    // 销毁之前,自动调用析构函数
}

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

构造函数的分类及调用

  • 按参数类型:分为无参构造函数和有参构造函数
  • 按类型分类:普通构造函数和拷贝构造函数(复制构造函数)
#include <iostream>
#include <string.h>
#include <string>
using namespace std;

class Person
{
public:
    // 构造函数 函数名和类名一致 没有返回值 不能写void 可以有参数 可以发生函数重载
    Person(int age, string name)
    {
        m_age = age;
        m_name = name;
        cout <<"can" <<endl;
    }
    Person(){
        cout <<"wu" <<endl;
    }

    // 析构函数 函数名:类名前加~  没有返回值 不可以有参数  不能发生函数重载
    ~Person()
    {
        cout <<"~~~~" <<endl;
    }

    // 拷贝构造的调用时机:旧对象初始化新对象
    Person(const Person &p)  // 这里的&是引用   常量引用
    {
        // 拷贝构造做了简单的值拷贝
        m_age = p.m_age;
        m_name = p.m_name;
        cout <<"copy.." <<endl;
    }

    int m_age;
    string m_name;
};

void test01()
{
    Person p1(10, "lucy");  // 构造函数是在实例化对象时会创建,就是在内存开辟空间时会被调用
    // 销毁之前,自动调用析构函数

    Person p2;   // 调用无参构造的时候,不能使用括号

    Person p3(p1);  // 调用了拷贝构造


}

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

构造函数的深浅拷贝

#include <iostream>
#include <string.h>
#include <string>
using namespace std;

class Person
{
public:
    Person(int age, char *str)
    {
        mAge = age;
        name = (char *)malloc(strlen(str)+1);
        strcpy(name, str);
        cout <<"cacaca" <<endl;
    }

    void show()
    {
        cout << mAge <<" " << name <<endl;
    }

    Person(const Person &p)   // 深拷贝   浅拷贝  编译器优化?
    {
        mAge = p.mAge;
        name = (char *)malloc(strlen(p.name)+1);
        strcpy(name, p.name);
    }

    ~Person()
    {
        cout <<"~~~~" <<endl;
        if(name != NULL)
        {
            free(name);
            name = NULL;
        }
    }

    int mAge;
    char *name;
};

void test01()
{
    Person p(10,"bob");
    p.show();

    Person p1(p);  // 调用拷贝构造函数
    p1.show();
}

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

类对象作为另外一个类的成员

  • 类中有多个对象时,构造的顺序是先构造里面的对象,再构造外面的对象
  • 类中有多个对象时,析构的顺序是先析构外面的对象,再析构里面的对象
#include <iostream>
#include <string.h>
#include <string>
using namespace std;

class Game
{
public:
    Game(){}

    Game(string gameA)
    {
        game = gameA;
    }

    string game;
};
class Phone
{
public:
    Phone(){}

    Phone(string phoneA)
    {
        phone = phoneA;
    }

    string phone;
};
class Person
{
public:

    // 初始化
    /*
    Person(string perName, string pho, string gam)
    {
        per_name = perName;
        Game.game = gam;
        Phone.phone = pho;
    }
    */

    Person(string perName, string pho, string gam):per_name(perName),phone(pho),game(gam)
    {
        cout <<" person... " <<endl;
    }


    void show()
    {
        cout << per_name << " "<< phone.phone << " " << game.game << endl;
    }

    string per_name;
    Game game;
    Phone phone;
};

void test01()
{
    Person p("aa","xiaomi","llkan");
    p.show();
}

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

malloc相关的问题
1、程序员必须确定对象的长度
2、malloc返回一个void指针,c++不允许将void赋值给其他任何指针,必须强转
3、malloc可能申请内存失败,所以必须判断返回值来确保内存分配成功
4、用户在使用对象之前,必须记住对它初始化。构造函数不能显示调用初始化(构造函数是由编译器调用),用户有可能忘记调用初始化函数

c的动态内存分配函数太复杂,容易令人混淆,是不可能接受的。

c++中我们推荐使用运算符 new 和 delete

#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
    Person()
    {
     cout<<"wu can"<<endl;
    }
    Person(int a1)
    {
        a = a1;
        cout<<"you can"<<endl;
    }
    ~Person()
    {
     cout<<"xi gou..."<<endl;
    }

    int a;
};

void test01()
{
    int *p = new int;  // 申请一块内存 sizeof(int)大小  并且对这块内存进行初始化
    cout <<*p <<endl;
    *p = 100;
    cout <<*p << endl;  // 100
    delete p;  // 释放申请的空间


    // 申请一个对象
    Person *p1 = new Person;  // sizeof(Person) 这里会调用无参构造函数
    delete p1;     // 会调用析构函数

    Person *p22 = new Person(10);  // new时调用有参构造
    delete p22;

    Person *p222 = new Person[3];  // new对象的数组时,不是调用有参构造,而是调用无参构造
    delete []p222;   // 得加[] ;  delete p222 ; 这个是删除首元素地址的意思

    // 申请一个数组
    int *p2 = new int[10];   // new一个数组时,返回的是该数组的首元素的地址
    for(int i=0; i<10; i++)
    {
        p2[i] = i+100;
    }
    for (int i=0; i<10; i++)
    {
        cout << p2[i] << " ";   // 100 101 102 103 104 105 106 107 108 109
    }
    cout << endl;
    delete []p2;    //  得加[] ;  delete p ; 这个是删除首元素地址的意思
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值