C++学习路线(二十二)

构造函数

构造函数作用

在创建一个新的对象时,自动调用的函数,用来进行“初始化”工作:对这个对象内部的数据成员进行初始化。

构造函数特点

1.自动调用(在创建新对象时,自动调用)

2.构造函数的函数名,和类名相同

3.构造函数没有返回类型

4.可以有多个构造函数(即函数重载形式)

构造函数种类

默认构造函数

自定义的构造函数

拷贝构造函数

赋值构造函数

默认构造函数

没有参数的构造函数,称为默认构造函数。

合成的默认构造函数

但没有手动定义默认构造函数时,编译器自动为这个类定义一个构造函数

1)如果数据成员使用了“类内初始值”,就使用这个值来初始化数据成员。

2)否则,就使用默认初始化(实际上,不做任何初始化)

#include <iostream>
using namespace std;class Human {
public:Human(){cout << "Human constructor called." << endl;}
};
int main() {Human p1;return 0;
}

只要手动定义了任何一个构造函数,编译器就不会生成“合成的默认构造函数”一般情况下,都应该定义自己的构造函数,不要使用“合成的默认构造函数”【仅当数据成员全部使用了“类内初始值”,才宜使用“合成的默认构造函数”】 

赋值构造函数

#include <iostream>
using namespace std;class Person {
public:void setAddr(char* p) {addr = p;}void description() const {cout << "Address: " << addr << endl;}
private:char* addr;
};int main() {char* str = new char[100] {"123 Main St"};Person p1;p1.setAddr(str);Person p2;p2 = p1; // 执行浅拷贝p1.description(); // 应该打印: Address: 123 Main Stp2.description(); // 应该也打印: Address: 123 Main St// 修改原始字符串,并查看 p1 和 p2 是否受到影响strncpy_s(str,100 ,  "456 Elm St" , _TRUNCATE );p1.description(); // 现在打印: Address: 456 Elm Stp2.description(); // 也打印: Address: 456 Elm Stdelete[] str; // 记得删除动态分配的内存return 0;
}

你执行 p2 = p1; 这一行时,默认情况下编译器会使用浅拷贝(shallow copy)。这意味着如果你的类中有指针或者持有对其他资源的引用的话,那么这些资源会被同样的引用到新的对象中去,而不是创建独立的副本。

我们可以自定义运算符重载Person& operator=(const Person& person)来实现深拷贝

#include <iostream>
using namespace std;class Person {
public:void setAddr(char* p) {addr = p;}void description() const {cout << "Address: " << addr << endl;}Person& operator=(const Person& p) {//防止对象自身赋值if (this == &p) return *this;//如果执行f2 = f1//就会调用f2.operator=(f1)//如果有必要 先释放自己的动态资源delete[] addr;//再拷贝p的动态资源到自己  addr = new char[strlen(p.addr) + 1];strcpy_s(addr, strlen(p.addr) + 1, p.addr);//返回对象本身的引用,是为了方便能够链式处理//f1 = f2 = f3return *this;}~Person() {delete[] addr;}
private:char* addr;
};int main() {char* str = new char[100] {"123 Main St"};Person p1;p1.setAddr(str);Person p2;p2 = p1; // 执行浅拷贝p1.description(); // 应该打印: Address: 123 Main Stp2.description(); // 应该也打印: Address: 123 Main St// 修改原始字符串,并查看 p1 和 p2 是否受到影响strncpy_s(str,100 ,  "456 Elm St" , _TRUNCATE );p1.description(); // 现在打印: Address: 456 Elm Stp2.description(); // 也打印: Address: 456 Elm Stdelete[] str; // 记得删除动态分配的内存return 0;
}

拷贝构造函数

#include <iostream>
using namespace std;class Person {
public:Person() {age = 0;name = "";}Person(const Person& p) {cout << "Copy constructor called." << endl;age = p.age;name = p.name;}void setAge(int a) {age = a;}void setName(string n) {name = n;}
private:int age;string name;
};int main() {Person p1;p1.setAge(25);p1.setName("John");Person p2(p1);Person p3 = p1;return 0;
}

合成的拷贝构造函数

        是指当类中没有显式定义拷贝构造函数时,编译器自动为该类生成的一个默认拷贝构造函数。这个自动生成的拷贝构造函数会执行成员变量的浅拷贝(shallow copy),即将源对象的每个成员变量的值直接复制到新创建的对象中。 简单来说,合并的拷贝构造函数是编译器在类定义中没有显式提供拷贝构造函数时自动提供的一个默认实现。这个默认实现会逐成员地复制源对象的值到新对象中,但它不会处理动态分配的内存(如指针指向的内存)的深拷贝(deep copy)问题,这可能会导致资源泄露或双重释放等问题。

合成的拷贝构造函数都是浅拷贝 下面给出一个浅拷贝的例子。

#include <iostream>
using namespace std;class Person {
public:void mallocAdress() {address = new char[100];}~Person() {if(address) delete[] address;}void print() {printf("address: %p\n", address);}
private:char* address = nullptr;
};int main() {Person p1;p1.mallocAdress();Person p2 = p1;Person p3(p1);p1.print();p2.print();return 0;
}

要解决合并的拷贝函数,我们可以自己定义一个拷贝构造函数

#include <iostream>
using namespace std;class Person {
public:void mallocAdress() {address = new char[100];}~Person() {if(address) delete[] address;}void print() {printf("address: %p\n", address);}Person(const Person& p) {address = new char[100];}
private:char* address = nullptr;
};int main() {Person p1;p1.mallocAdress();Person p2 = p1;Person p3(p1);p1.print();p2.print();return 0;
}
什么时候调用拷贝构造函数

1.调用函数时,实参是对象,形参不是引用类型

#include <iostream>
using namespace std;class MyClass {
public:MyClass(int val) {this->val = val;cout << "Constructor called" << endl;}MyClass(const MyClass& obj) {cout << "Copy constructor called" << endl;this->val = obj.val;}int val;
};void func(MyClass obj) {cout << "Value of obj is " << obj.val << endl;
}int main() {MyClass obj1(10);func(obj1);return 0;
}

2.函数的返回类型是类,而且不是引用类型

#include <iostream>class MyClass {
public:MyClass(int val) : value(val) {std::cout << "MyClass constructor called." << std::endl;}MyClass(const MyClass& other) : value(other.value) {std::cout << "Copy constructor called." << std::endl;}int value;
};
MyClass returnObject() {MyClass temp(20);return temp; // 返回局部变量会调用拷贝构造函数
}
int main() {MyClass returned = returnObject(); // 这里也会调用拷贝构造函数std::cout << "Returned object value: " << returned.value << std::endl;return 0;
}

虽然会因为RVO优化,不调用MyClass的拷贝构造函数

3.对象数组的初始化列表中,使用对象。

#include <iostream>class MyClass {
public:MyClass(int val) : value(val) {std::cout << "MyClass constructor called." << std::endl;}MyClass(const MyClass& other) : value(other.value) {std::cout << "Copy constructor called." << std::endl;}int value;
};int main() {MyClass source(30);MyClass array[3] = { source, source, source }; // 这里会三次调用拷贝构造函数for (int i = 0; i < 3; ++i) {std::cout << "Array[" << i << "] value: " << array[i].value << std::endl;}return 0;
}

类和基本数据不同(int , float , double , long , long long)

类的构成:方法和数据

#include <iostream>
using namespace std;
class Human {
public:int age;string name;void print() {cout << "Name: " << name << ", Age: " << age << endl;}Human() {cout << "Constructor called." << endl;}Human(const Human& h) {cout << "Copy constructor called." << endl;}Human& operator=(const Human& h) {cout << "Assignment operator called." << endl;return *this;}~Human() {cout << "Destructor called." << endl;}
};
int main() {Human h1;cout << "---" << endl;Human* h2 = &h1;return 0;
}

上面以指针的形式来进行初始化的话不会调用拷贝

如果某数据成员使用类内初始值,同时又在构造函数中进行了初始化

那么以构造函数中的初始化为准

相当于构造函数中的初始化,会覆盖对应的类内初始值

#include <iostream>class MyClass {
public:MyClass() : value(10) { // 类内初始化std::cout << "Default constructor called." << std::endl;}MyClass(int val) : value(val) { // 构造函数初始化std::cout << "Constructor with initial value called." << std::endl;}MyClass(const MyClass& other) : value(other.value) { // 拷贝构造函数std::cout << "Copy constructor called." << std::endl;}void printValue() const {std::cout << "Value is: " << value << std::endl;}private:int value = 5; // 类内初始值
};int main() {MyClass obj1; // 使用类内默认构造函数obj1.printValue(); // 输出 Value is: 10MyClass obj2(20); // 使用构造函数初始化obj2.printValue(); // 输出 Value is: 20return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pytorch学习--如何下载及使用Pytorch中自带数据集,如何把数据集和transforms联合在一起使用

一、标准数据集使用 pytorch官网–标准数据集 这里以CIFAR10数据集为例&#xff1a;CIFAR10 下载数据集 代码&#xff1a; import torchvision train_datatorchvision.datasets.CIFAR10(root"datasets",trainTrue,downloadTrue) test_datatorchvision.datasets.…

盘古信息制造数字化优才计划 | 解决人才困境 赋能智能制造

在中国制造2025的大背景下&#xff0c;制造业正以前所未有的速度向数字化、智能化转型。在这场深刻的变革中&#xff0c;人才作为核心驱动力&#xff0c;其重要性日益凸显。作为全球领先的制造运营管理工业软件供应商&#xff0c;盘古信息深知构建制造人才生态的重要性&#xf…

EasyExcel_动态表头的导入导出

文章目录 前言一、EasyExcel二、使用步骤1.引入jar包2.数据准备2.1 数据库 3.方法实例3.1 无实体的导入3.1.1 Controller3.1.2 Service3.1.3 Listener3.1.4 Utils3.1.5 无实体导入数据返回说明 3.2 无实体的导出3.2.1 无实体导出数据(这里只贴出关键代码,Service代码处理)3.2.2…

Kafka Tool(Offset Explorer)在windows下配置访问kerberos认证Kafka

Author : Spinach | GHB Link : http://blog.csdn.net/bocai8058文章目录 前言准备配置文件配置软件参数及启动 前言 Offset Explorer&#xff08;以前称为Kafka Tool&#xff09;是一个用于管理和使用Apache Kafka集群的图形用户界面&#xff08;GUI&#xff09;应用程序。…

登录时用户名密码加密传输(包含前后端代码)

页面输入用户名密码登录过程中&#xff0c;如果没有对用户名密码进行加密处理&#xff0c;可能会导致传输过程中数据被窃取&#xff0c;就算使用https协议&#xff0c;在浏览器控制台的Request Payload中也是能直接看到传输的明文&#xff0c;安全感是否还是不足。 大致流程&a…

FreeRTOS代码规范(3)

数据类型 portmacro.h : 在里面定义了Free RTOS 用到的相关数据类型 在 CM-3 内核中 short类型是16位&#xff0c;long 类型是32位 在 portmacro.h 中有两个最基本的数据类型 &#xff1a; Base type_t Tick type_t 这两个数据类型的存在是基于执行效率考虑的&#xff0c;…

如何使用 NumPy 和 Matplotlib 进行数据可视化

如何使用 NumPy 和 Matplotlib 进行数据可视化 在数据科学领域&#xff0c;NumPy 和 Matplotlib 是 Python 中最常用的两个库。NumPy 用于科学计算和数据处理&#xff0c;而 Matplotlib 提供了丰富的图表工具来展示数据。本文将介绍如何将这两个库结合使用&#xff0c;轻松进行…

腾讯会议pc端3.29.11开启悬浮窗口

之前是&#xff1a;pc端每次最小化&#xff0c;它就自动收回到任务栏里了 版本&#xff1a;3.29.11 解决办法&#xff1a; 打开腾讯会议&#xff0c;点击左上角的【头像】。 单击【设置】。 选择【显示当前说话者】来管理麦克风浮窗。 再进入会议&#xff0c;点击最小化一哈&…

中小企业设备资源优化:Spring Boot系统实现

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

RabbitMQ常见问题持续汇总

文章目录 消息分发不公平分发限流-basic.qos主要功能使用场景示例代码 消费者默认concurrency数量prefetch和concurrency结合&#xff1f; spring.rabbitmq.template.retry.enabledtrue和spring.rabbitmq.listener.simple.retry.enabledtrue有什么区别1. spring.rabbitmq.templ…

Appium环境搭建全流程(含软件)

目录 1.node.js的安装 1--中文下载地址 2--node.js设置镜像源 2.安装appium 1--全局安装appium 2--安装驱动 uiautomator2 3--查看插件的命令 4--安装 images插件 5--安装 execute-driver 插件 6--安装 relaxed-caps插件 7--安装 universal-xml 插件 3.python安装 1--python下…

Excel功能区变灰是什么原因造成?怎么解决?

Microsoft Excel是广泛使用的电子表格软件&#xff0c;但有时用户可能会遇到功能区变灰的问题&#xff0c;这可能导致功能无法使用&#xff0c;影响工作效率和用户体验。本文将深入探讨Excel功能区灰色的原因及解决方案&#xff0c;帮助读者快速解决这一问题。 一、Excel功能区…

Windows 使用命令行开启热点(无线网卡连接下)

winr 打开命令提示符框&#xff08;管理员模式&#xff09;在cmd中输入 netsh wlan show drivers 检查无线网卡是否已插入继续输入 ssid后面是wifi名称&#xff0c;key后面是密码&#xff0c;可以自行更改 netsh wlan set hostednetwork modeallow ssidWDW keyWDWWDWWDW 设置热…

开源模型应用落地-Qwen2.5-7B-Instruct与vllm实现推理加速的正确姿势-Gradio

一、前言 目前&#xff0c;Qwen模型已经升级到了2.5版本。无论是语言模型还是多模态模型&#xff0c;它们都是在大规模的多语言和多模态数据上进行预训练的&#xff0c;并通过高质量的数据进行后期微调&#xff0c;以更好地符合人类的需求。 Gradio作为一个强大的工具&#xff…

APP专项测试-冷启动-流量-电量-内存

1、响应时间 1.1怎么获取冷启动时间&#xff08;热启动&#xff0c;就是后台不关后台再次打开&#xff09; 方法一 1.2怎么获取包名 与 启动页 方法三soloPi&#xff1a;启动时间(用户角度出发&#xff0c;页面差异进行计算时间)&#xff1a; 然后默认配置。点击开始录制 1开…

云计算行业应用实训室建设方案

一、引言 云计算作为信息技术领域的重要分支&#xff0c;正在深刻影响着各行各业的发展。随着云计算技术的不断成熟和应用领域的不断拓展&#xff0c;对云计算专业人才的需求日益增长。实训室作为培养学生实践能力和创新能力的重要场所&#xff0c;其建设对于提高教育质量和满…

模拟信号采集显示器+GPS同步信号发生器制作全过程(焊接、问题、代码、电路)

1、制作最小系统板 在制作最小系统板的时候&#xff0c;要用USB转TTL给板子供电&#xff0c;留了一个电源输入的四个接口&#xff0c;同时又用排针引出来VCC和GND用于后续其他外设的电源供应&#xff0c;电源配有电源指示灯和保护电容&#xff0c; 当时在焊接的时候把接口处的…

数学建模与优化算法:从基础理论到实际应用

数学建模和优化算法&#xff0c;它们不仅帮助我们理解和描述复杂系统的行为&#xff0c;还能找到系统性能最优化的解决方案。本文将从基础的数学理论出发&#xff0c;逐步深入到各种优化算法&#xff0c;并探讨它们在实际问题中的应用。 思维导图文件可获取&#xff1a;https:…

51单片机应用开发(进阶)---外部中断(按键+数码管显示0-F)

实现目标 1、巩固数码管、外部中断知识 2、具体实现&#xff1a;按键K4&#xff08;INT1&#xff09;每按一次&#xff0c;数码管从0依次递增显示至F&#xff0c;再按则循环显示。 一、共阳数码管 1.1 共阳数码管结构 1.2 共阳数码管码表 共阳不带小数点0-F段码为&#xff…

Python异常检测- DBSCAN

系列文章目录 Python异常检测- Isolation Forest&#xff08;孤立森林&#xff09; python异常检测 - 随机离群选择Stochastic Outlier Selection (SOS) python异常检测-局部异常因子&#xff08;LOF&#xff09;算法 文章目录 系列文章目录前言一、DBSCAN算法原理二、DBSCAN算…