C++中的构造函数和析构函数

本文介绍了C++中的构造函数,包括其功能、默认构造函数、构造函数重载以及构造初始化列表的使用。接着讨论了拷贝构造函数,区分了浅拷贝和深拷贝的概念,并通过示例展示了它们的区别。最后,提到了析构函数的作用,即在对象销毁时自动调用以释放资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

构造函数的概念:

构造函数是类中一种特殊的函数,构造函数的功能有:

(1)创见对象

(2)对属性进行初始化

如果程序员不在类中写构造函数,编译器会自动添加一个没有参数的、函数体为空的构造函数

注意:

(1)构造函数不写返回值,因为返回值是创建的对象

(2)函数名称必须与类名相同

代码示例:
#include <iostream>

using namespace std;
class MobilePhone
{
private:
    string brand = "华为";
    string model = "p50";
    int weight = 188;
public:
   MobilePhone() // 如果不写,编译器自动添加
   {
       cout << "创建了一个对象" << endl; // 默认的构造函数没有这句

   }

   void show()
   {
       cout << brand << " " << model << " " << weight << endl;
   }
};

int main()
{
    MobilePhone mp1; // 调用默认构造函数
    mp1.show();

    return 0;
}

构造函数重载:

构造函数支持重载,如果程序员手写任何一个构造函数,则编译器不再添加默认的无参构造函数

此时如果仍要调用无参构造函数且手写的不是无参的构造函数时,则需要利用构造函数重载来实现多个构造函数

构造函数的调用是强制的,一旦在类中定义了构造函数,那么创建对象时就一定要调用,不调用就是错误的。如果有多个重载的构造函数,那么创建对象时提供的实参必须和其中的一个构造函数匹配;反过来说,创建对象时只有一个构造函数被调用

代码示例:
#include <iostream>

using namespace std;
class MobilePhone
{
private:
    string brand;
    string model;
    int weight;
public:
   MobilePhone(string b,string m,int w)
   {
       brand = b;
       model = m;
       weight = w;
   }

   MobilePhone()
   {
       brand = "华为";
       model = "P50";
       weight = 188;
   }

   void show()
   {
       cout << brand << " " << model << " " << weight << endl;
   }
};

int main()
{
    MobilePhone mp1("小米","13",188);
    mp1.show(); // 小米 13 188

    MobilePhone* mp2 = new MobilePhone("苹果","14",177);  //堆内存对象,手动开辟手动释放
    mp2->show();
    delete mp2; // 苹果 14 177

    MobilePhone mp3;
    mp3.show(); // 华为 P50 188

    return 0;
}

构造初始化列表:

构造初始化列表与构造函数的函数体的区别

(1)如果成员变量是const修饰的,不能使用构造函数的函数体赋值

(2)构造初始化列表要比函数体中的赋值执行效率更高

如果构造初始化列表影响了代码的可读性,也可以考虑不使用或者混用

代码示例:
#include <iostream>

using namespace std;
class MobilePhone
{
private:
    string brand;
    string model;
    int weight;
public:
   // 使用构造初始化列表赋值
   MobilePhone(string b,string m,int w):brand(b),model(m),weight{w}{}

   void show()
   {
       cout << brand << " " << model << " " << weight << endl;
   }
};

int main()
{
    MobilePhone mp1("小米","13",188);
    mp1.show(); // 小米 13 188

    return 0;
}

混用也是可以的

#include <iostream>

using namespace std;
class MobilePhone
{
private:
    string brand;
    string model;
    int weight;
public:
   // 混用
    MobilePhone(string b,string m,int w):brand(b),weight{w}
       {
            model = m;
       }

   void show()
   {
       cout << brand << " " << model << " " << weight << endl;
   }
};

int main()
{
    MobilePhone mp1("小米","13",188);
    mp1.show(); // 小米 13 188

    return 0;
}

拷贝构造函数:

如果程序员不手写拷贝构造函数,编译器会自动添加一个拷贝构造函数,与其他的构造函数重载,以便于对象的拷贝构建

拷贝构造函数分为两类:

(1)浅拷贝

浅拷贝只进行赋值,如果对象中的某个成员是指针类型数据,直接复制操作会导致两个指针保存的地址相同,指向同一份内存,这不符合面向对象的特性

浅拷贝中,如果对象中的某个成员是指针类型数据,且所指之物在堆区创建,则使用浅拷贝仅仅是对指针的赋值,让指针也指向这一块内存空间,在析构的时候,会造成析构同一块内存空间多次引起程序崩溃

示例代码:
#include <iostream>
#include <string.h>

using namespace std;
class Dog
{
private:
    char* name; // 指针

public:
    Dog(char* n)
    {
        name = n;
    }

    // 复现默认的拷贝构造函数
    Dog(const Dog& d)
    {
        name = d.name; // 浅拷贝
    }

    void show_name()
    {
        cout << name << endl;
    }
};

int main()
{
    char c[20] = "wangcai";

    Dog d1(c);
    Dog d2(d1); // 拷贝构造函数

    strcpy(c,"xiaobai");

    d1.show_name(); // xiaobai
    d2.show_name(); // xiaobai

    return 0;
}
(2)深拷贝

深拷贝首先开辟和源对象大小相同的一块空间,然后将源对象拷贝到目标中去,这样指针成员就指向了不同的地址空间,不会出现析构多次同一空间的情况

代码示例:
#include <iostream>
#include <string.h>

using namespace std;
class Dog
{
private:
    char* name; // 指针

public:
    Dog(char* n)
    {
        name = new char[20];
        strcpy(name,n);
    }

    Dog(const Dog& d)
    {
        name = new char[20]; // 深拷贝
        strcpy(name,d.name);
    }

    void show_name()
    {
        cout << name << endl;
    }
};


int main()
{
    char c[20] = "wangcai";

    Dog d1(c);
    Dog d2(d1); // 拷贝构造函数

    strcpy(c,"xiaobai");

    d1.show_name(); // wangcai
    d2.show_name(); // wangcai

    return 0;
}

析构函数:

析构函数是与构造函数独立的函数,在同一个对象销毁时,析构函数可以自动被调用,通常在析构函数中执行一些对象占用资源的回收等收尾工作

代码示例:
#include <iostream>

using namespace std;
class Cat
{
private:
    string name;
public:
    Cat(string n)
    {
        name = n;
    }

    ~Cat()
    {
        cout << name << "猫死了" << endl;
    }
};

int main()
{
    Cat* c3 = new Cat("丙");
    // 独立代码块:表示一个局部范围
    {
        Cat c1("甲");
        cout << "}" << endl;
    }
    Cat c2("乙");

    delete c3;

    cout << "主函数结束" << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值