C++构造和折构函数详解,超详细!

个人主页:PingdiGuo_guo

收录专栏:C++干货专栏

大家龙年好呀,今天我们来学习一下C++构造函数和折构函数。

文章目录

1.构造函数

1.1构造函数的概念

1.2构造函数的思想

1.3构造函数的特点

1.4构造函数的作用

1.5构造函数的操作

1.6构造函数的分类

1.6.1默认构造函数(Default Constructor)

1.6.2带参数构造函数(Parameterized Constructor)

1.6.3拷贝构造函数(Copy Constructor)

1.6.4移动构造函数(Move Constructor)

1.6.5委托构造函数(Delegating Constructor)

1.6.6虚拟构造函数(Virtual Constructor)

1.7构造函数的练习

1.7.1题目

1.7.2步骤

1.7.3代码

2.折构函数

2.1折构函数的概念

2.2折构函数的思想

2.3折构函数的特点

2.4折构函数的作用

2.5折构函数的操作

2.6折构函数的分类

2.6.1默认析构函数

2.6.2有特定目的的析构函数

3.构造函数和折构函数的利弊

3.1利

3.2弊

4.总结


1.构造函数

1.1构造函数的概念

构造函数是C++中的特殊成员函数,用于初始化新创建的对象。当一个类的对象被声明并实例化时,构造函数自动被调用。它的主要作用是确保对象在其生命周期开始时就处于有效状态。

1.2构造函数的思想

构造函数的思想是在创建对象时,用于初始化对象的成员变量和执行其他必要的操作。构造函数在对象创建时自动调用,不需要手动调用。构造函数的主要目的是确保对象被正确地初始化,以便在使用对象时不会出现未定义的行为或错误。

1.3构造函数的特点

1.构造函数的名称与类名称相同,并且没有返回类型(包括void类型),包括默认构造函数和带参数的构造函数。

2.构造函数可以重载,即在同一个类中可以定义多个具有不同参数列表的构造函数。

3.构造函数可以带有参数,在创建对象时,可以根据传递的参数值来初始化对象的成员变量。

4.构造函数可以进行一些初始化操作,例如分配内存、调用其他对象的构造函数等。

5.构造函数可以被继承,子类可以调用父类的构造函数来初始化父类的成员变量。

1.4构造函数的作用

1.对象的初始化:构造函数用于初始化对象的成员变量,确保对象在创建时具有正确的初始状态。

2.分配和初始化成员变量:构造函数可以分配并初始化类的成员变量,以便在对象创建时设置默认值或特定的初始状态。

3.进行必要的前置操作:构造函数可以执行一些必要的前置操作,例如打开文件、连接数据库等。

4.为对象分配内存:构造函数负责为对象分配内存空间,这通常发生在通过 new 运算符创建对象时。

5.链接到其他对象或资源:构造函数可以将对象链接到其他对象或资源,以便对象能够使用这些外部资源。

6.初始化对象的状态:构造函数可以设置对象的初始状态,例如设置指针成员变量为 null、设置计数器为 0 等。

7.执行其他必要的操作:构造函数还可以执行其他与对象创建相关的必要操作,如申请资源、注册回调函数等。

8.为派生类提供基类的初始化:在派生类的构造函数中,可以通过调用基类的构造函数来初始化继承自基类的成员变量。

1.5构造函数的操作

1. 定义类结构:
 

class Book {
private:
char* title; // 私有成员变量,用于存储动态分配的标题字符串

public:
// 构造函数声明
Book(const char* t);
};



2. 实现构造函数:
在类外部实现构造函数,它负责接收一个 C 风格字符串并将其复制到动态分配的内存中。
 

Book::Book(const char* t) {
// 计算字符串长度(包括终止符 '\0')
size_t len = strlen(t) + 1;

// 动态分配内存
title = new char[len];

// 使用标准库函数strcpy复制字符串
strcpy(title, t);
}




3. 构造函数操作:
当创建 Book 对象时,构造函数会被自动调用:
 

int main() {
Book book("The Title of the Book"); // 这里调用了构造函数
// ...
return 0;
}


在上述代码中,当我们创建 book对象时,传入的字符串 "The Title of the Book"将被复制到通过 new分配的内存空间中。

1.6构造函数的分类

构造函数可以分为以下几种分类:

1.6.1默认构造函数(Default Constructor)

如果一个类没有定义任何构造函数,那么编译器会自动生成一个默认构造函数。默认构造函数没有任何参数,并且不进行任何初始化操作。

class MyClass {
public:
    // 默认构造函数
    MyClass() {
        // 进行初始化操作
    }
};

int main() {
    // 创建一个对象,调用默认构造函数
    MyClass obj;
    return 0;
}

1.6.2带参数构造函数(Parameterized Constructor)

带参数构造函数接收一定数量和类型的参数,用于对对象的成员变量进行初始化。通过传递不同的参数值,可以创建具有不同初始状态的对象。

class MyClass {
public:
    // 带参数构造函数
    MyClass(int value) {
        // 进行初始化操作,使用参数value对对象进行初始化
    }
};

int main() {
    // 创建一个对象,调用带参数构造函数
    MyClass obj(10);
    return 0;
}

1.6.3拷贝构造函数(Copy Constructor)

拷贝构造函数是一种特殊的构造函数,用于创建一个新对象,并将现有对象的值复制到新对象中。拷贝构造函数通常用于对象之间的值传递或对象的复制。

class MyClass {
public:
    // 拷贝构造函数
    MyClass(const MyClass& other) {
        // 进行拷贝操作,将other对象的值复制到当前对象中
    }
};

int main() {
    // 创建一个对象,调用拷贝构造函数
    MyClass obj1;
    MyClass obj2 = obj1;  // 或者 MyClass obj2(obj1);
    return 0;
}

1.6.4移动构造函数(Move Constructor)

移动构造函数是C++11引入的一种特殊构造函数,用于将右值引用参数转移或"窃取"其资源,而不是进行复制。移动构造函数可以提高程序的效率和性能。

class MyClass {
public:
    // 移动构造函数
    MyClass(MyClass&& other) {
        // 进行移动操作,将other对象的资源移动到当前对象中
    }
};

int main() {
    // 创建一个对象,调用移动构造函数
    MyClass obj1;
    MyClass obj2 = std::move(obj1);  // 或者 MyClass obj2(std::move(obj1));
    return 0;
}

1.6.5委托构造函数(Delegating Constructor)

委托构造函数是C++11引入的一种特殊构造函数,它允许一个构造函数调用同一个类的另一个构造函数,以避免代码冗余。

class MyClass {
public:
    // 默认构造函数
    MyClass() : MyClass(0) {
        // 委托给带参数的构造函数
    }
    
    // 带参数构造函数
    MyClass(int value) {
        // 进行初始化操作,使用参数value对对象进行初始化
    }
};

int main() {
    // 创建一个对象,调用默认构造函数
    MyClass obj;
    return 0;
}

1.6.6虚拟构造函数(Virtual Constructor)

虚拟构造函数是一种在基类中声明的构造函数,用于在派生类中动态创建基类对象。虚拟构造函数是通过在基类中声明纯虚函数来实现的。

class Base {
public:
    // 虚拟构造函数
    virtual Base* clone() const {
        return new Base(*this);
    }
    
    // 其他成员函数和数据成员
};

class Derived : public Base {
public:
    // 虚拟构造函数的重写
    virtual Derived* clone() const {
        return new Derived(*this);
    }
    
    // 其他成员函数和数据成员
};

int main() {
    // 创建一个派生类对象,调用虚拟构造函数的重写
    Base* basePtr = new Derived();
    Base* copy = basePtr->clone();
    
    // 其他操作
    
    delete basePtr;
    delete copy;
    return 0;
}

1.7构造函数的练习

1.7.1题目

设计并实现一个 Person类,其中包含姓名和年龄属性,并编写一个自定义构造函数来初始化这些属性。

1.7.2步骤

1. 定义 `Person` 类结构,声明私有成员变量。
2. 编写构造函数,接受姓名(字符串类型)和年龄(整型)作为参数。
3. 在构造函数内,对传入的参数进行有效性检查(可选)。
4. 将传入的参数值赋给对应的成员变量。

1.7.3代码

// Step 1: 定义 Person 类
class Person {
private:
    std::string name;
    int age;

public:
    // Step 2: 编写构造函数
    Person(const std::string& n, int a) {
        // Step 3: 参数有效性检查(例如年龄应该大于0)
        if (a < 0) {
            throw std::invalid_argument("Age must be positive.");
        }

        // Step 4: 赋值给成员变量
        name = n;
        age = a;
    }

    // 其他成员函数...
};

// 使用构造函数创建一个 Person 对象
int main() {
    Person person("John Doe", 30);
    return 0;
}

2.折构函数

2.1折构函数的概念

析构函数是C++中另一种特殊的成员函数,它与构造函数相反,在对象生命周期结束时(例如对象的作用域结束或者delete一个动态分配的对象时)自动调用。析构函数主要用于清理工作,如释放内存、关闭文件等。

2.2折构函数的思想

析构函数是一种特殊的成员函数,在对象销毁时自动调用,用于释放对象所占用的资源。

析构函数与构造函数相对应,构造函数用于对象的初始化,而析构函数用于对象的清理与释放。

2.3折构函数的特点

1.析构函数没有参数,且没有返回值。

2.析构函数的名称与类名相同,前面加上波浪号(~)作为前缀。

3.只能有一个析构函数,且不能被继承或重载。

4.析构函数不能被显式地调用,不能被重载。

5.对象销毁时,析构函数会自动调用,从而完成对象的销毁和资源的释放。

6.析构函数按照对象的创建顺序的逆序调用,即先创建的对象后销毁。

2.4折构函数的作用

1.释放动态分配的内存或资源。

2.关闭打开的文件、数据库连接等。

3.清理对象中的临时数据和状态。

4.执行其他清理和释放操作。

2.5折构函数的操作

1. 定义析构函数:
在类内部声明析构函数,它将在 Book 对象生命周期结束时(例如,超出作用域或显式销毁)自动调用。
 

class Book {
// ...
public:
// 析构函数声明
~Book();
};



2. 实现析构函数:
在类外部实现析构函数,它负责释放之前构造函数中动态分配的内存。
 

Book::~Book() {
// 检查指针是否已经分配过内存
if (title != nullptr) {
delete[] title; // 释放内存
title = nullptr; // 设置为 nullptr 防止悬挂指针
}
}



3. 析构函数操作:
析构函数的操作是自动的,不需要程序员显式调用。当 Book对象离开其作用域时,析构函数会自动执行。
 

int main() {
{
Book book("The Title of the Book"); // 创建对象时构造函数被调用
} // 这里 book 作用域结束,析构函数将被自动调用,释放 title 的内存
return 0;
}


在上述代码中,当 book 对象超出作用域时,析构函数将被调用,释放之前为 title分配的内存。这样就确保了程序不会出现内存泄漏的问题。

2.6折构函数的分类

析构函数的分类主要分为默认析构函数和有特定目的的析构函数。

2.6.1默认析构函数

如果在类中没有显式定义析构函数,编译器会自动生成一个默认的析构函数。默认析构函数会自动释放对象占用的内存,但不执行任何其他操作。


 

class MyClass {
public:
    // 构造函数
    MyClass() {
        // 构造函数的代码
    }
    // 默认析构函数
    ~MyClass() {
        // 自动生成的析构函数,无需显式定义
    }
};

2.6.2有特定目的的析构函数

有些情况下,需要在对象销毁时执行特定的清理操作,例如释放资源、关闭文件、释放动态分配的内存等。这时可以自定义析构函数,并在其中编写相应的清理代码。


 

class MyClass {
private:
    int* ptr; // 动态分配的内存指针

public:
    // 构造函数
    MyClass() {
        ptr = new int[10]; // 动态分配内存
    }

    // 有特定目的的析构函数
    ~MyClass() {
        delete[] ptr; // 释放动态分配的内存
    }
};

在上述代码中,我们定义了一个具有特定目的的析构函数,用于释放动态分配的内存。当对象销毁时,析构函数会自动被调用,执行内存释放操作。

需要注意的是,每个类只能有一个析构函数,不能重载析构函数。析构函数没有参数,也没有返回值。析构函数的名称与类名称相同,并在前面加上波浪线(~)作为标识。

使用析构函数可以确保在对象生命周期结束时进行清理工作,避免内存泄漏和资源浪费的问题。同时,通过自定义析构函数,可以根据具体需求执行特定的清理操作。

3.构造函数和折构函数的利弊

3.1利


- 构造函数确保了对象从一开始就处于已知的良好状态。
- 析构函数提供了自动资源管理机制,减少内存泄漏和其他资源泄露的风险。



3.2弊


- 如果构造函数或析构函数内部逻辑复杂,可能影响程序性能或增加错误的可能性。
- 构造函数抛出异常会导致未初始化的对象,而析构函数如果在异常处理期间抛出异常,则可能导致程序行为不可预测。

4.总结

本篇博客到这里就结束了,感谢大家的支持与观看,如果有好的建议欢迎留言,谢谢大家啦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/383577.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

洗地机哪个品牌最耐用质量好?耐用的洗地机型号

相较于传统的打扫方式&#xff0c;洗地机的出现可以称得上是懒人福音。一台洗地机就能包办吸、扫、拖所有清洁步骤&#xff0c;节省了大量的打扫时间。不过最近几年洗地机行业涌入的品牌属实有些鱼龙混杂了&#xff0c;至于型号就更是乱七八糟&#xff0c;稍不留神就会白白花了…

深度学习之线性模型

深度学习之线性模型 y w * x模型思路 y w * x b模型思路 y w * x模型 思路 这里求权重w , 求最适合的权重&#xff0c;就是求损失值最小的时候 这里用穷举法:在一个范围内&#xff0c;列出w的所有值&#xff0c;并且计算出每组数据的平均损失值,以w 为横坐标, 损失值为纵坐…

【射影几何15】python双曲几何工具geometry_tools

目录 一、说明二、​环境问题&#xff1a;如何安装三、实现一个简单的例子四、绘制双曲组五、使用有限状态自动机加快速度六、资源和代码 一、说明 Geometry_tools 是一个 Python 包&#xff0c;旨在帮助您处理和可视化双曲空间和射影空间上的群动作。 该包主要构建在 numpy、…

C语言求解猴子分桃子

问题&#xff1a;海滩上有一堆桃子&#xff0c;五只猴子来分。第一只猴子把这堆桃子平均分为五份&#xff0c;多了一个&#xff0c;这只 猴子把多的一个扔入海中&#xff0c;拿走了一份。第二只猴子把剩下的桃子又平均分成五份&#xff0c;又多了 一个&#xff0c;它同样把多的…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Divider组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Divider组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Divider组件 提供分隔器组件&#xff0c;分隔不同内容块/内容元素。 子组件 …

2024年湖南省考报名时间及流程,选岗很重要!

注册时间&#xff1a;2024年2月18日9:00-25日17:00 报名时间&#xff1a;2024年2月19日9:00-25日17:00 网上确认时间&#xff1a;2024年2月28日9:00-3月2日24:00 缴费时间&#xff1a;2024年2月28日9:00-3月2日24:00 打印准考证时间&#xff1a;2024年3月11日9:00-15日17:00 考…

漂亮不是工业HMI的追求?我劝你,这个想法要变了

对于工业HMI&#xff08;Human Machine Interface&#xff09;来说&#xff0c;漂亮并不是唯一的追求&#xff0c;但它仍然是一个重要的方面。在工业环境中&#xff0c;HMI的设计需要考虑到使用者的工作效率和安全性&#xff0c;因此功能性和易用性是首要考虑的因素。然而&…

【EAI 015】CLIPort: What and Where Pathways for Robotic Manipulation

论文标题&#xff1a;CLIPort: What and Where Pathways for Robotic Manipulation 论文作者&#xff1a;Mohit Shridhar1, Lucas Manuelli, Dieter Fox1 作者单位&#xff1a;University of Washington, NVIDIA 论文原文&#xff1a;https://arxiv.org/abs/2109.12098 论文出处…

【计算机网络】网络基础入门

需要云服务器等云产品来学习Linux的同学可以移步/–>腾讯云<–/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;优惠多多。&#xff08;联系我有折扣哦&#xff09; 文章目录 1. 局域网和广域网2. 协议2.1 认识协议2.2 协议分层 3. OSI七层模型和TCP五层&#x…

Ainx-V0.2-简单的连接封装与业务绑定

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于Ainx系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系列…

vue中watch和computed的不同

第076个 查看专栏目录: VUE ------ element UI Vue.js 中的 watch 和 computed 都是用于监听数据变化并执行相应操作的选项&#xff0c;但它们的使用场景和优劣势有所不同。 两者区别 watch 用于监听一个或多个数据属性的变化&#xff0c;并在变化时执行相应的处理函数。 它…

Windows快捷键大全(包含语音输入、剪切板历史快捷键)

最近发现了微软官网上给出的快捷键大全&#xff0c;并且使用了其中几个新的键盘快捷键&#xff08;语音输入、剪切板历史&#xff09;&#xff0c;确实方便快捷&#xff0c;所以写个博客记录分享一下。 注&#xff1a;windows快捷键大全微软官方已经给出&#xff0c;此处不再赘…

中创ET4410 台式LCR数字电桥 简单开箱测评

最近买了一台LCR电桥&#xff0c;完善一下自己实验室的设备&#xff0c;选了中创ET4410&#xff0c;这款性价比高一点。 1199元在PDD买的&#xff0c;好像胜利的VC4090C也是找中创代工的。 ET4410介绍 本系列LCR数字电桥是采用自动平衡电桥原理设计的元件参数分析仪&#xf…

数据库恢复

文章目录 前言一、事务1.概念2.定义语句3.ACID特性 二、数据库恢复的必要性1.为什么要进行数据库恢复2.数据库恢复机制的作用 三、数据恢复使用的技术1.数据转储2.登记日志文件 四 、不同故障的数据恢复策略1.事务内部的故障2.系统故障3.介质故障 五、具有检查点的恢复技术1.检…

JVM学习记录

JVM基础概念 JVM是一个运行在计算机上的程序&#xff0c;负责编译java字节码文件&#xff0c;支持跨平台特性。 java语言为了通过实时解释实现多平台支持&#xff0c;性能相对于C等语言较低&#xff0c;而JVM提供了JIT即时编译进行性能优化。 JVM与JIT JVM负责解释和执行Ja…

13 年后,我如何用 Go 编写 HTTP 服务(译)

原文&#xff1a;Mat Ryer - 2024.02.09 大约六年前&#xff0c;我写了一篇博客文章&#xff0c;概述了我是如何用 Go 编写 HTTP 服务的&#xff0c;现在我再次告诉你&#xff0c;我是如何写 HTTP 服务的。 那篇原始的文章引发了一些热烈的讨论&#xff0c;这些讨论影响了我今…

go安装与设置

开发环境 安装 下载地址 https://golang.org/dl/(国外的可能不能访问) https://studygolang.com/dl(国内网址,推荐) 安装 下载完成后点击运行,一直next,就可以,安装成功后打开winR输入cmd打开命令行输入go env, 输出 证明安装成功 改变$GOPATH $GOPATH是go存储第三方包和编…

《UE5_C++多人TPS完整教程》学习笔记4 ——《P5 局域网连接(LAN Connection)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P5 局域网连接&#xff08;LAN Connection&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;也是译者&…

精品springboot善筹网(众筹)互助前后台购物商城实现设计

《[含文档PPT源码等]精品基于springboot善筹网(众筹)前后台实现设计[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; Java——涉及技术&#xff1a; 前端使用技术&#xf…

数学实验第三版(主编:李继成 赵小艳)课后练习答案(八)(4)

实验八&#xff1a;近似计算 练习四 1.自己设置一种计算欧拉常数近似值的方法&#xff0c;看你对欧拉常数的计算能精确到小数点后多少位&#xff1f; 从示例7的图8.5我们已经得知&#xff0c;只要求出每个小矩形中在函数y1/x以上的部分的面积之和&#xff0c;我们就可以得知…