当前位置: 首页 > news >正文

【知识点】 C++ 构造函数 参数类型为右值引用的模板函数

C++ 构造函数是一种特殊的成员函数,用于初始化类对象。C++ 中的构造函数主要分为以下几种类型:

  1. 默认构造函数(Default Constructor)
  2. 参数化构造函数(Parameterized Constructor)
  3. 拷贝构造函数(Copy Constructor)
  4. 移动构造函数(Move Constructor)
  5. 委托构造函数(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&(左值引用),而当 20std::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 构造函数是一种特殊的成员函数&#xff0c;用于初始化类对象。C 中的构造函数主要分为以下几种类型&#xff1a; 默认构造函数&#xff08;Default Constructor&#xff09;参数化构造函数&#xff08;Parameterized Constructor&#xff09;拷贝构造函数&#xff08;Copy C…...

华为云服务器-云容器引擎 CCE环境构建及项目部署

1、切换地区 2、搜索云容器引擎 CCE 3、购买集群 4、创建容器节点 通过漫长的等待(五分钟左右)&#xff0c;由创建中变为运行中&#xff0c;则表明容器已经搭建成功 购买成功后&#xff0c;返回容器控制台界面 5、节点容器管理 6、创建redis工作负载 7、创建mysql工作负载 8、…...

Linux shell编程学习笔记57:lshw命令 获取cpu设备信息

0 前言 在Linux中&#xff0c;获取cpu信息的命令很多&#xff0c;除了我们已经研究的 cat /proc/cpuinfo、lscpu、nproc、hwinfo --cpu 命令&#xff0c;还有 lshw命令。 1 lshw命令的功能 lshw命令源自英文list hardware&#xff0c;即列出系统的硬件信息&#xff0c;这些硬…...

连山露【诗词】

连山露 雾隐黄山路&#xff0c;十步一松树。 树上惊松鼠&#xff0c;松子衔木屋。 松子青嫩芽&#xff0c;尖尖头探出。 卷挂白露珠&#xff0c;装映黄山雾。...

【Qt】Frame和Widget的区别

1. 这两个伙计有啥区别&#xff1f; 2. 区别 2.1 Frame继承自Widget&#xff0c;多了一些专有的功能 Frame Widget 2.2 Frame可以设置边框...

Python爬虫实战:从入门到精通

网络爬虫&#xff0c;又称为网络蜘蛛或爬虫&#xff0c;是一种自动浏览网页的程序&#xff0c;用于从互联网上收集信息。Python由于其简洁的语法和强大的库支持&#xff0c;成为开发网络爬虫的首选语言。 环境准备 Python安装 必要的库&#xff1a;requests, BeautifulSoup, Sc…...

堆算法详解

目录 堆 二叉堆的实现 二叉堆的插入 二叉堆取出堆顶 &#xff08;extract/delete max&#xff09; 优先对列 (priority queue) 堆的实现 语言中堆的实现 leadcode 题目堆应用 堆 堆是一种高效维护集合中最大或最小元素的数据结构。 大根堆&#xff1a;根节点最大的堆…...

6.6SSH的运用

ssh远程管理 ssh是一种安全通道协议&#xff0c;用来实现字符界面的远程登录。远程复制&#xff0c;远程文本传输。 ssh对通信双方的数据进行了加密 用户名和密码登录 密钥对认证方式&#xff08;可以实现免密登录&#xff09; ssh 22 网络层 传输层 数据传输的过程中是加密的 …...

MySQL-备份(三)

备份作用&#xff1a;保证数据的安全和完整。 一 备份类别 类别物理备份 xtrabackup逻辑备份mysqldump对象数据库物理文件数据库对象&#xff08;如用户、表、存储过程等&#xff09;可移植性差&#xff0c;不能恢复到不同版本mysql对象级备份&#xff0c;可移植性强占用空间占…...

结构体(1)<C语言>

导言 结构体是C语言中的一种自定义类型&#xff0c;它的值&#xff08;成员变量&#xff09;可以是多个&#xff0c;且这些值可以为不同类型&#xff0c;这也是和数组的主要区别&#xff0c;下面将介绍它的一些基本用法&#xff0c;包括&#xff1a;结构体的创建、结构体变量的…...

HW面试应急响应之场景题

(1)dns 报警就一定是感染了吗&#xff1f;怎么处理&#xff1f; 不一定。 引起dns报警的情况有&#xff1a;恶意软件感染&#xff0c;域名劫持&#xff0c;DNS欺骗&#xff0c;DDoS攻击等。 处理方法&#xff1a; 1、分析报警&#xff0c;查看报警类型、源IP地址、目标域名等…...

30-unittest生成测试报告(HTMLTestRunner插件)

批量执行完测试用例后&#xff0c;为了更好的展示测试报告&#xff0c;最好是生成HTML格式的。本文使用第三方HTMLTestRunner插件生成测试报告。 一、导入HTMLTestRunner模块 这个模块下载不能通过pip安装&#xff0c;只能下载后手动导入&#xff0c;下载地址是&#xff1a;ht…...

鸿蒙北向开发 IDE DevEco Studio 3.1 傻瓜式安装闭坑指南

首先下载 安装IDE 本体程序 DevEco Studio 下载链接 当前最新版本是3.1.1,下载windows版本的 下载下来后是一个压缩包, 解压解锁包后会出现一个exe安装程序 双击运行安装程序 一路 next ( 这里涉及安装文件目录,我因为C盘够大所以全部默认了,各位根据自己情况选择自己的文件…...

Oracle数据库面试题-9

81. 请解释Oracle数据库中的林业数据处理方法。 Oracle数据库中的林业数据处理 在Oracle数据库中处理林业数据涉及到存储、管理、分析和可视化与林业相关的数据。以下是林业数据处理的一些关键方面以及如何使用Oracle数据库进行示例性的SQL说明&#xff1a; 数据库设计&#…...

跟着小白学linux的基础命令

小白学习记录&#xff1a; 前情提要&#xff1a;Linux命令基础格式!查看 lsLinux 的7种文件类型及各颜色代表含义 进入指定目录 cd查看当前工作目录 pwd创建一个新的目录(文件夹&#xff09; 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” 脚本&#xff0c;并将其放在 Editor 文件…...

Mac下删除系统自带输入法ABC,正解!

一、背景说明 MacOS 在 14.2 以下的系统存在中文输入法 BUG&#xff0c;会造成系统卡顿&#xff0c;出现彩虹圆圈。如果为了解决这个问题&#xff0c;有两种方法&#xff1a; 升级到最新的 14.5 系统使用第三方输入法 在使用第三方输入法的时候&#xff0c;会发现系统自带的 …...

redis学习路线

待更新… 一、nosql讲解 1. 为什么要用nosql&#xff1f; 用户的个人信息&#xff0c;社交网络&#xff0c;地理位置&#xff0c;自己产生的数据&#xff0c;日志等等爆发式增长&#xff01;传统的关系型数据库已无法满足这些数据处理的要求&#xff0c;这时我们就需要使用N…...

数据库练习题

1行程和用户 表&#xff1a;Trips ----------------------- | Column Name | Type | ----------------------- | id | int | | client_id | int | | driver_id | int | | city_id | int | | status | enum | | request_at…...

【每日一函数】uname 函数介绍及代码演示

Linux uname 函数介绍及代码演示 引言 Linux 系统中&#xff0c;uname 是一个常用的命令行工具&#xff0c;用于显示系统信息。然而&#xff0c;在编程过程中&#xff0c;我们有时需要在程序中获取这些信息&#xff0c;此时就可以使用 uname 函数。本文将对 uname 函数进行详…...

linux:命令别名,文件描述符及重定向

命令别名 命令别名是Shell提供的一种快捷方式&#xff0c;允许为命令创建简短的替代名称。&#xff0c;可以通过输入较短的别名来执行较长的命令&#xff0c;从而提高效率。 1.查看所有别名: [rootlocalhost ~]# alias 2.创建临时别名,当前会话关闭即清除 alias 别名完整命令…...

前端开发之中svg图标的使用和实例

svg图标的使用和实例 前言效果图1、安装插件2、vue3中使用2.1、 在components文件夹中,创建公共类SvgIcon/index.vue2.2、创建icons文件,存放svg图标和将所有的svg图标进行引用并注册成全局组件2.3、在man.js 中注册2.4、在vue.config.js中配置svg2.5、在vue中的调用svg图标3…...

BeagleBone Black入门总结

文章目录 参考连接重要路径系统镜像下载访问 BeagleBone 参考连接 镜像下载启动系统制作&#xff1a;SD卡烧录工具入门书籍推荐&#xff1a;BeagleBone cookbookBeagleBone概况&#xff1f; 重要路径 官方例程及脚本路径&#xff1a;/var/lib/cloud9 系统镜像下载 疑问&am…...

笔记:Mysql的安全策略

1&#xff0c;安装安全插件 1.检查是否已安装该插件 SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME validate_password;2.安装插件 INSTALL PLUGIN validate_password SONAME validate_password.so;3.修改配置文件 vi /etc/my.cn…...

AI绘画中的图像格式技术

在数字艺术的广阔天地里&#xff0c;AI绘画作为一种新兴的艺术形式&#xff0c;正在逐渐占据一席之地。不同于传统绘画&#xff0c;AI绘画依赖于复杂的算法和机器学习模型来生成图像&#xff0c;而这一切的背后&#xff0c;图像格式技术发挥着至关重要的作用。图像格式不仅关系…...

前端如何封装自己的npm包并且发布到npm注册源

前言 在前端开发中&#xff0c;复用代码是一种常见且高效的实践。通过封装和发布自己的npm包&#xff0c;你可以轻松地在多个项目之间共享代码&#xff0c;并且贡献给社区。以下是一步一步指导你如何封装自己的npm包并发布到npm注册源。 步骤一&#xff1a;创建并设置项目 首…...

vue油色谱画 大卫三角形|大卫五边形|PD图

大卫三角形 大卫五边形 PD图...

【React】前端插件 uuidjs 的使用 --随机生成id

文档1 文档2 使用 1.安装 npm install uuid2.Create a UUID import { v4 as uuidv4 } from uuid; uuidv4(); // ⇨ 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d3.或使用 CommonJS语法 const { v4: uuidv4 } require(uuid); uuidv4(); // ⇨ 1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4…...

ctfshow-web入门-信息搜集(web11-web20)

目录 1、web11 2、web12 3、web13 4、web14 5、web15 6、web16 7、web17 8、web18 9、web19 10、web20 1、web11 域名其实也可以隐藏信息&#xff0c;比如flag.ctfshow.com 就隐藏了一条信息 查询域名的 DNS 记录&#xff0c;类型为 TXT&#xff08;域名的说明&#…...

C语言详解(动态内存管理)2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…...

黑龙江省垦区建设协会网站/武汉seo托管公司

西雅图IT圈&#xff1a;seattleit【今日作者】宇直宇宙第一直男近日有网友发现疑似刘强东的证件照被强行植入进了某印度电影的预告片里疑似造成了侵权这部电影播出了预告片片中大概40秒处有一幕镜头是&#xff1a;疑似正在进行案件分析&#xff0c;墙面上出现了许多照片&#x…...

wordpress评论采集插件/新手seo要学多久

接口与类的调用在java并发编程开发项目中是非常常见的一种开发需求&#xff0c;而今天我们就通过案例分析来了解一下&#xff0c;java并发编程常见的接口与类都有哪些类型。1、接口:ConditionCondition为接口类型&#xff0c;它将Object监视器方法(wait、notify和notifyAll)分解…...

综合网站建设课程设计/搜索引擎营销优化

存储过程: procedure 概念类似于函数,就是把一段代码封装起来, 当要执行这一段代码的时候,可以通过调用该存储过程来实现. 在封装的语句体里面,可以用if/else, case,while等控制结构. 可以进行sql编程. 查看现有的存储过程: Show procedure status 删除存储过程 Drop procedure…...

hao123手机浏览器/天天seo百度点击器

https://blog.csdn.net/xqhrs232/article/details/13507543 2种方法&#xff1a;1&#xff1a;在PCB中进入ECO模式-选择要更新的元件-点击change component图标-&#xff08;选中元件后&#xff09;右键点击元件-在弹出的菜单中选择libraby browse-勾选update part type from l…...

优秀网站建设哪家便宜/seo在线优化技术

什么是IPython&#xff1f;可能很多人已经在用&#xff0c;却不知道它到底是什么。 根据维基百科的解释&#xff1a;IPython是一种基于Python的交互式解释器&#xff0c;提供了强大的编辑和交互功能。IPython拥有&#xff1a;满足你各种需求的交互式shell火爆数据科学社区的Jup…...

软件上传网站/东莞seo代理

最近数码圈新机发布的少&#xff0c;但操作系统却打的火热。这边鸿蒙OS2.0刚刚公测&#xff0c;那边Android 12系统就正式登场了。谷歌正式发布Android 12(1)开放的系统风格与操作界面这么多年以来&#xff0c;国产手机用的基本上都是安卓系统&#xff0c;虽然它们在此基础上设…...