【知识点】 C++ 构造函数 参数类型为右值引用的模板函数
C++ 构造函数是一种特殊的成员函数,用于初始化类对象。C++ 中的构造函数主要分为以下几种类型:
- 默认构造函数(Default Constructor)
- 参数化构造函数(Parameterized Constructor)
- 拷贝构造函数(Copy Constructor)
- 移动构造函数(Move Constructor)
- 委托构造函数(Delegating Constructor)
1. 默认构造函数(Default Constructor)
默认构造函数是在没有提供参数的情况下调用的构造函数。如果程序员没有定义构造函数,编译器会生成一个隐式默认构造函数。程序员也可以显式定义默认构造函数。
示例
class MyClass {
public:MyClass() {std::cout << "Default Constructor called" << std::endl;}
};int main() {MyClass obj; // 调用默认构造函数return 0;
}
2. 参数化构造函数(Parameterized Constructor)
参数化构造函数允许在创建对象时传递参数,以便初始化对象的成员。
示例
class MyClass {
private:int value;
public:MyClass(int v) : value(v) {std::cout << "Parameterized Constructor called with value: " << value << std::endl;}
};int main() {MyClass obj(10); // 调用参数化构造函数return 0;
}
3. 拷贝构造函数(Copy Constructor)
拷贝构造函数用于创建一个新的对象,并用现有对象初始化它。其参数是现有对象的引用,通常是 const 引用。
示例
class MyClass {
private:int value;
public:MyClass(int v) : value(v) {std::cout << "Parameterized Constructor called with value: " << value << std::endl;}MyClass(const MyClass& other) : value(other.value) {std::cout << "Copy Constructor called" << std::endl;}
};int main() {MyClass obj1(10); // 调用参数化构造函数MyClass obj2 = obj1; // 调用拷贝构造函数return 0;
}
4. 移动构造函数(Move Constructor)
移动构造函数用于接管另一个对象的资源,而不是拷贝其值。这对于优化性能和避免不必要的拷贝操作特别有用。移动构造函数的参数是一个右值引用。
示例
#include <utility> // std::moveclass MyClass {
private:int* value;
public:MyClass(int v) : value(new int(v)) {std::cout << "Parameterized Constructor called with value: " << *value << std::endl;}~MyClass() {delete value;}MyClass(const MyClass& other) : value(new int(*other.value)) {std::cout << "Copy Constructor called" << std::endl;}MyClass(MyClass&& other) noexcept : value(other.value) {other.value = nullptr;std::cout << "Move Constructor called" << std::endl;}
};int main() {MyClass obj1(10); MyClass obj2 = std::move(obj1); // 调用移动构造函数return 0;
}
参数类型为右值引用的模板函数在 C++ 中用于实现完美转发(perfect forwarding)和移动语义(move semantics)。右值引用(T&&)和模板结合使用,可以创建灵活、高效的代码。
右值引用与模板的结合
在模板中使用右值引用,可以通过类型推导实现完美转发。完美转发是指将参数完整地传递给另一个函数,保持参数的原始类型(左值或右值)和属性。
示例:右值引用的模板函数
基本模板函数
下面是一个接受右值引用参数的模板函数示例:
#include <iostream>
#include <utility> // std::forwardtemplate<typename T>
void process(T&& arg) {std::cout << "Processing" << std::endl;// 使用 arg
}int main() {int x = 10;process(x); // x 是左值process(20); // 20 是右值process(std::move(x)); // std::move(x) 是右值return 0;
}
完美转发
为了实现完美转发,使用 std::forward 函数。std::forward 会根据参数的实际类型(左值或右值)进行转发。
示例:完美转发
#include <iostream>
#include <utility> // std::forwardvoid print(int& t) {std::cout << "Lvalue: " << t << std::endl;
}void print(int&& t) {std::cout << "Rvalue: " << t << std::endl;
}template<typename T>
void forwarder(T&& arg) {print(std::forward<T>(arg)); // 完美转发
}int main() {int x = 10;forwarder(x); // 转发左值forwarder(20); // 转发右值forwarder(std::move(x)); // 转发右值return 0;
}
在这个示例中,forwarder 函数使用 std::forward 将参数 arg 转发给 print 函数。std::forward<T>(arg) 保留了参数的类型属性,确保 print 函数根据参数的实际类型调用正确的重载版本。
深入理解 T&& 在模板中的行为
在模板中,T&& 表示万能引用(universal reference),即它可以绑定到左值或右值。如果你传递的是左值,那么 T 推导为左值引用类型。如果你传递的是右值,那么 T 推导为非引用类型。
示例
#include <iostream>
#include <type_traits>template<typename T>
void check(T&& arg) {if (std::is_lvalue_reference<T>::value) {std::cout << "T is lvalue reference" << std::endl;} else {std::cout << "T is not lvalue reference" << std::endl;}if (std::is_rvalue_reference<decltype(arg)>::value) {std::cout << "arg is rvalue reference" << std::endl;} else {std::cout << "arg is not rvalue reference" << std::endl;}
}int main() {int x = 10;check(x); // 左值传递check(20); // 右值传递check(std::move(x)); // 右值传递return 0;
}
输出结果:
T is lvalue reference
arg is not rvalue reference
T is not lvalue reference
arg is rvalue reference
T is not lvalue reference
arg is rvalue reference
从输出结果可以看出,当 x 是左值时,T 被推导为 int&(左值引用),而当 20 和 std::move(x) 是右值时,T 被推导为 int(非引用类型)。
- 右值引用与模板结合:
T&&在模板中被称为万能引用,可以绑定左值或右值。 - 完美转发:使用
std::forward<T>(arg)实现完美转发,保持参数的类型属性。 - 万能引用的类型推导:
T&&可以根据传递参数的类型(左值或右值)进行不同的类型推导。
5. 委托构造函数(Delegating Constructor)
委托构造函数是在同一个类中,一个构造函数调用另一个构造函数,以避免重复代码和简化初始化过程。
示例
class MyClass {
private:int value1;int value2;
public:MyClass(int v1, int v2) : value1(v1), value2(v2) {std::cout << "Constructor with two parameters called" << std::endl;}MyClass(int v) : MyClass(v, 0) {std::cout << "Delegating Constructor called" << std::endl;}MyClass() : MyClass(0, 0) {std::cout << "Default Delegating Constructor called" << std::endl;}
};int main() {MyClass obj1; // 调用委托的默认构造函数MyClass obj2(10); // 调用委托的单参数构造函数MyClass obj3(10, 20); // 调用带两个参数的构造函数return 0;
}
总结
- 默认构造函数:无参数构造函数,可以由编译器生成或显式定义。
- 参数化构造函数:带有参数的构造函数,用于初始化对象时传递参数。
- 拷贝构造函数:使用现有对象初始化新对象的构造函数,参数是对象的
const引用。 - 移动构造函数:接管另一个对象的资源,参数是对象的右值引用。
- 委托构造函数:一个构造函数调用另一个构造函数,以避免代码重复和简化初始化。
通过理解这些构造函数,可以更好地设计和管理 C++ 类对象的初始化过程。如果你有更多问题或需要进一步解释,请告诉我!
相关文章:
【知识点】 C++ 构造函数 参数类型为右值引用的模板函数
C 构造函数是一种特殊的成员函数,用于初始化类对象。C 中的构造函数主要分为以下几种类型: 默认构造函数(Default Constructor)参数化构造函数(Parameterized Constructor)拷贝构造函数(Copy C…...
华为云服务器-云容器引擎 CCE环境构建及项目部署
1、切换地区 2、搜索云容器引擎 CCE 3、购买集群 4、创建容器节点 通过漫长的等待(五分钟左右),由创建中变为运行中,则表明容器已经搭建成功 购买成功后,返回容器控制台界面 5、节点容器管理 6、创建redis工作负载 7、创建mysql工作负载 8、…...
Linux shell编程学习笔记57:lshw命令 获取cpu设备信息
0 前言 在Linux中,获取cpu信息的命令很多,除了我们已经研究的 cat /proc/cpuinfo、lscpu、nproc、hwinfo --cpu 命令,还有 lshw命令。 1 lshw命令的功能 lshw命令源自英文list hardware,即列出系统的硬件信息,这些硬…...
连山露【诗词】
连山露 雾隐黄山路,十步一松树。 树上惊松鼠,松子衔木屋。 松子青嫩芽,尖尖头探出。 卷挂白露珠,装映黄山雾。...
【Qt】Frame和Widget的区别
1. 这两个伙计有啥区别? 2. 区别 2.1 Frame继承自Widget,多了一些专有的功能 Frame Widget 2.2 Frame可以设置边框...
Python爬虫实战:从入门到精通
网络爬虫,又称为网络蜘蛛或爬虫,是一种自动浏览网页的程序,用于从互联网上收集信息。Python由于其简洁的语法和强大的库支持,成为开发网络爬虫的首选语言。 环境准备 Python安装 必要的库:requests, BeautifulSoup, Sc…...
堆算法详解
目录 堆 二叉堆的实现 二叉堆的插入 二叉堆取出堆顶 (extract/delete max) 优先对列 (priority queue) 堆的实现 语言中堆的实现 leadcode 题目堆应用 堆 堆是一种高效维护集合中最大或最小元素的数据结构。 大根堆:根节点最大的堆…...
6.6SSH的运用
ssh远程管理 ssh是一种安全通道协议,用来实现字符界面的远程登录。远程复制,远程文本传输。 ssh对通信双方的数据进行了加密 用户名和密码登录 密钥对认证方式(可以实现免密登录) ssh 22 网络层 传输层 数据传输的过程中是加密的 …...
MySQL-备份(三)
备份作用:保证数据的安全和完整。 一 备份类别 类别物理备份 xtrabackup逻辑备份mysqldump对象数据库物理文件数据库对象(如用户、表、存储过程等)可移植性差,不能恢复到不同版本mysql对象级备份,可移植性强占用空间占…...
结构体(1)<C语言>
导言 结构体是C语言中的一种自定义类型,它的值(成员变量)可以是多个,且这些值可以为不同类型,这也是和数组的主要区别,下面将介绍它的一些基本用法,包括:结构体的创建、结构体变量的…...
HW面试应急响应之场景题
(1)dns 报警就一定是感染了吗?怎么处理? 不一定。 引起dns报警的情况有:恶意软件感染,域名劫持,DNS欺骗,DDoS攻击等。 处理方法: 1、分析报警,查看报警类型、源IP地址、目标域名等…...
30-unittest生成测试报告(HTMLTestRunner插件)
批量执行完测试用例后,为了更好的展示测试报告,最好是生成HTML格式的。本文使用第三方HTMLTestRunner插件生成测试报告。 一、导入HTMLTestRunner模块 这个模块下载不能通过pip安装,只能下载后手动导入,下载地址是:ht…...
鸿蒙北向开发 IDE DevEco Studio 3.1 傻瓜式安装闭坑指南
首先下载 安装IDE 本体程序 DevEco Studio 下载链接 当前最新版本是3.1.1,下载windows版本的 下载下来后是一个压缩包, 解压解锁包后会出现一个exe安装程序 双击运行安装程序 一路 next ( 这里涉及安装文件目录,我因为C盘够大所以全部默认了,各位根据自己情况选择自己的文件…...
Oracle数据库面试题-9
81. 请解释Oracle数据库中的林业数据处理方法。 Oracle数据库中的林业数据处理 在Oracle数据库中处理林业数据涉及到存储、管理、分析和可视化与林业相关的数据。以下是林业数据处理的一些关键方面以及如何使用Oracle数据库进行示例性的SQL说明: 数据库设计&#…...
跟着小白学linux的基础命令
小白学习记录: 前情提要:Linux命令基础格式!查看 lsLinux 的7种文件类型及各颜色代表含义 进入指定目录 cd查看当前工作目录 pwd创建一个新的目录(文件夹) mkdir创建文件 touch查看文件内容 cat、more操作文件、文件夹- 复制 cp- 移动 mv- 删…...
2024-06-08 Unity 编辑器开发之编辑器拓展9 —— EditorUtility
文章目录 1 准备工作2 提示窗口2.1 双键窗口2.2 三键窗口2.3 进度条窗口 3 文件面板3.1 存储文件3.2 选择文件夹3.3 打开文件3.4 打开文件夹 4 其他内容4.1 压缩纹理4.2 查找对象依赖项 1 准备工作 创建脚本 “Lesson38Window.cs” 脚本,并将其放在 Editor 文件…...
Mac下删除系统自带输入法ABC,正解!
一、背景说明 MacOS 在 14.2 以下的系统存在中文输入法 BUG,会造成系统卡顿,出现彩虹圆圈。如果为了解决这个问题,有两种方法: 升级到最新的 14.5 系统使用第三方输入法 在使用第三方输入法的时候,会发现系统自带的 …...
redis学习路线
待更新… 一、nosql讲解 1. 为什么要用nosql? 用户的个人信息,社交网络,地理位置,自己产生的数据,日志等等爆发式增长!传统的关系型数据库已无法满足这些数据处理的要求,这时我们就需要使用N…...
数据库练习题
1行程和用户 表:Trips ----------------------- | Column Name | Type | ----------------------- | id | int | | client_id | int | | driver_id | int | | city_id | int | | status | enum | | request_at…...
【每日一函数】uname 函数介绍及代码演示
Linux uname 函数介绍及代码演示 引言 Linux 系统中,uname 是一个常用的命令行工具,用于显示系统信息。然而,在编程过程中,我们有时需要在程序中获取这些信息,此时就可以使用 uname 函数。本文将对 uname 函数进行详…...
深度学习赋能国税局发票查验:中英文混合验证码的高效识别方案
1. 验证码识别的税务场景痛点 每次打开国税局网站查验发票时,那个扭曲变形的中英文混合验证码是不是让你特别头疼?作为财务人员,我每天要处理上百张发票,手动输入这些验证码不仅效率低下,还容易出错。传统OCR技术在这里…...
AI语音智能体赋能12345热线,实现政务服务数智化
12345政务服务便民热线作为连接政府与群众的“连心桥”,承载着政策咨询、诉求举报、民生求助等核心职能,是政务服务的重要窗口。但随着民生需求日益多元,传统12345热线逐渐面临话务高峰拥堵、人工座席压力大、响应效率不均、诉求闭环不及时等…...
Kettle(二)资源库配置实战:从创建到高效连接
1. 为什么需要Kettle资源库? 第一次接触Kettle时,我习惯把转换和作业脚本直接保存在本地。直到某天电脑突然蓝屏,辛苦写好的ETL脚本全部丢失,才意识到资源库的重要性。Kettle资源库就像是一个"代码保险箱",它…...
NCMconverter完整指南:3步解锁NCM音乐文件的终极播放方案
NCMconverter完整指南:3步解锁NCM音乐文件的终极播放方案 【免费下载链接】NCMconverter NCMconverter将ncm文件转换为mp3或者flac文件 项目地址: https://gitcode.com/gh_mirrors/nc/NCMconverter 你是否曾经遇到过这样的情况:从音乐平台下载了心…...
内容解锁工具:突破付费墙限制的开源解决方案
内容解锁工具:突破付费墙限制的开源解决方案 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 在信息爆炸的数字时代,优质内容常被付费墙阻隔,形成信…...
深入解析Bluetooth AVDTP协议:音频/视频传输的核心机制
1. 蓝牙AVDTP协议初探:音频视频传输的幕后英雄 每次用蓝牙耳机听音乐或看视频时,你可能没意识到背后有个"隐形交通警察"在指挥数据流动。这个默默工作的角色就是AVDTP协议(Audio/Video Distribution Transport Protocol)…...
ClickHouse 3节点集群配置与分布式表实战指南
1. ClickHouse集群基础概念解析 第一次接触ClickHouse集群时,我被各种术语绕得头晕——分片、副本、分布式表、本地表,这些概念到底有什么区别?后来在实际项目中踩过几次坑才真正理解它们的含义。简单来说,**分片(Shar…...
百川2-13B驱动OpenClaw智能客服:电商售后场景的自动化响应实战
百川2-13B驱动OpenClaw智能客服:电商售后场景的自动化响应实战 1. 为什么选择OpenClaw搭建轻量级客服系统 去年双十一期间,我运营的小型电商店铺遭遇了售后咨询暴增的问题。临时雇佣的客服人员不熟悉产品细节,导致大量重复问题需要反复解答…...
中文语义相似度计算新范式:技术演进与实践路径
中文语义相似度计算新范式:技术演进与实践路径 【免费下载链接】Awesome-Chinese-LLM 整理开源的中文大语言模型,以规模较小、可私有化部署、训练成本较低的模型为主,包括底座模型,垂直领域微调及应用,数据集与教程等。…...
GPT-4o 新手入门指南:从零开始构建你的第一个智能对话应用
GPT-4o 新手入门指南:从零开始构建你的第一个智能对话应用 作为一名刚接触大模型开发的程序员,面对 GPT-4o 这样的新工具,你是不是既兴奋又有点无从下手?看着官方文档里一堆 API 参数,想着怎么管理好几轮对话的上下文…...
