【C++入门】(拷贝)构造函数和析构函数

1、构造函数和析构函数

(1)构造函数(constructor):字面意思就是构造对象的函数,当我们定义类的对象时调用,可以帮我们完成对象的初始化;
(2)析构函数(destructor):可以看做是构造函数的逆过程,当销毁类的时候调用,做一些收尾的工作;比如:定义类的对象时构造函数申请了动态内存,那在销毁对象时调研员的析构函数中就要释放申请的动态内存,否则就会造成内存泄漏;
(3)构造/析构函数是C++语言自带的回调函数。程序员可以在定义类时使用默认的构造/析构函数,或者自己定义构造/析构函数,但是构造/析构函数的调用却不是程序员主动去调用,而是C++语言自动帮我们调用。比如:定义类的对象时就会自动调用构造函数,销毁类的时候就会调用析构函数,程序员只需要定义类或者销毁类,构造/析构函数的调用是自动的;

2、构造函数和析构函数的使用

(1)C++在定义类时会提供默认的构造/析构函数,默认的构造/析构函数可以看做是空函数,什么也没做,如果我们没有需求可以在类中不定义构造/析构函数;
(2)如果我们在类中定义了构造/析构函数,则C++提供的默认构造/析构函数就失效了,只会调用自定义的构造/析构函数;
(3)构造和析构函数不需要返回值类型,构造函数可以带参或不带参,析构函数不带参;
(4)构造函数可以重载(overload),析构函数不需要重载;
(5)构造函数的名字就是类的名字,析构函数的名字是"~ + 类名";

3、为什么需要构造函数和析构函数

(1)在C语言中只有struct没有class,所以C语言没有构造/析构函数的概念,C语言程序员定义struct后,需要手动去给struct结构体成员初始化;
(2)C++是面向对象的语言,class的封装性比struct更好。
(3)比如:class中有个成员变量是指针,如果没有构造/析构函数,则需要定义对象后手动去为指针申请动态内存,在销毁对象前,手动去释放动态内存;现在动态内存的申请/释放可以放到构造/析构函数中,使用class的程序员不必再操心动态内存的申请释放;

4、不使用动态内存的构造/析构函数

4.1、示例代码

#include <iostream>

using namespace std;

class Person{
public:
    int age;

    string getName(void) const;

    //构造函数
    Person();
    Person(string myname);
    
	 // 析构函数
    ~Person();	

private:
    string name;    //人的名字
    mutable int getNameCnt; //名字被查询的次数

};


int main(void)
{
	//定义对象,此时会调用构造函数
	Person *p1 = new Person ("linux");

    cout << "p1.name=" << p1->getName() << endl;
	
    //   销毁对象
    delete(p1);

	return 0;
}

string Person::getName(void) const
{
    this->getNameCnt++;
    cout << "getNameCnt=" << this->getNameCnt << endl;
    return this->name;
}

//  使用参数列表的方式
Person::Person()
{
        cout << "Person::Person()" << endl;
        this->getNameCnt=0;
};

//  构造函数:使用参数列表的方式
Person::Person(string myname):name(myname)
{
       //this->name=myname;	//等同于上面参数列表的形式
        cout << "Person::Person(string myname):name(myname)" << endl;
        this->getNameCnt=0;
};

// 析构函数:在没有使用动态内存的情况下,析构函数一般都是空函数
Person::~Person()
{
      cout << "~Person" << endl;
};

4.2、代码分析

root@ubuntu:# ./app 
Person::Person(string myname):name(myname)
getNameCnt=1
p1.name=linux
~Person

(1)在定义对象时调用了构造函数,调用的是传string形式的,因为构造函数支持函数重载,并且定义定义对象时传入了string的参数;
(2)在销毁对象时调用了析构函数;

5、使用动态内存的构造/析构函数

5.1、示例代码

#include <iostream>

using namespace std;

class Person{
public:
    int age;

    string getName(void) const;

    //构造函数
    Person();
    Person(string myname);

     // 析构函数
    ~Person();

private:
    string *name;    //人的名字
    mutable int getNameCnt; //名字被查询的次数

};

int main(void)
{
    //定义对象,此时会调用构造函数
    Person *p1 = new Person ("linux");

    cout << "p1.name=" << p1->getName() << endl;

    //   销毁对象
    delete(p1);

    return 0;
}

string Person::getName(void) const
{
    this->getNameCnt++;
    cout << "getNameCnt=" << this->getNameCnt << endl;
    return *this->name;
}

//  使用参数列表的方式
Person::Person()
{
        cout << "Person::Person()" << endl;
        this->getNameCnt=0;
};

//  构造函数
Person::Person(string myname)
{
        this->name = new string(); //申请动态内存
        
       *this->name=myname;
        cout << "Person::Person(string myname):name(myname)" << endl;
        this->getNameCnt=0;
};

// 析构函数
Person::~Person()
{
      cout << "[~Person] delete this->name" << endl;
      delete (this->name);	//释放在构造函数中申请的动态内存
};

5.2、代码分析

root@ubuntu:# ./app 
Person::Person(string myname):name(myname)
getNameCnt=1
p1.name=linux
[~Person] delete this->name

(1)上第4节的代码相比,将class中name变量从string类型变成string指针类型;
(2)在构造函数中为string指针申请内存,在析构函数中释放内存;
总结:如果类中使用动态内存,可以在构造函数中申请,在析构函数中释放,使用类的程序员不用再操作内存的申请释放;

6、拷贝构造函数

参考博客:《【C++入门】拷贝构造函数》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值