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

c++(强生成关键字+可变参数模板+emplace)[26]

强制生成 不生成

在C++中,可以通过一些方式来控制编译器是否生成某些特殊成员函数(如默认构造函数、拷贝构造函数、拷贝赋值运算符、析构函数等)。

  1. 默认生成:如果你没有显式地定义这些特殊成员函数,编译器会自动生成它们。这被称为默认生成。默认生成的成员函数会根据类的特性进行生成,例如默认构造函数会生成一个无参构造函数,拷贝构造函数会生成一个按值拷贝的构造函数。

  2. 强制生成:如果你显式地声明了某个特殊成员函数,但是不提供其定义,编译器将不会生成该函数的默认实现。这被称为强制生成。通过强制生成,你可以禁止某些特殊成员函数的自动生成,从而实现特定的语义或行为。

  3. 不生成:如果你显式地删除了某个特殊成员函数,编译器将不会生成该函数的默认实现。这被称为不生成。通过不生成,你可以禁止某些特殊成员函数的使用,从而防止不希望的行为或错误。

下面是一些示例代码,展示了如何强制生成或不生成特殊成员函数:

class MyClass {
public:// 强制生成默认构造函数MyClass() = default;// 强制生成拷贝构造函数MyClass(const MyClass& other) = default;// 不生成拷贝赋值运算符MyClass& operator=(const MyClass& other) = delete;// 强制生成析构函数~MyClass() = default;
};

在上面的示例中,我们通过使用default关键字来强制生成默认构造函数、拷贝构造函数和析构函数。同时,我们通过使用delete关键字来不生成拷贝赋值运算符。

需要注意的是,强制生成或不生成特殊成员函数是一种高级用法,需要谨慎使用。你应该根据具体的需求和设计来决定是否需要强制生成或不生成某些特殊成员函数。

// 以下代码在vs2013中不能体现,在vs2019下才能演示体现上面的特性。
class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}Person(const Person& p):_name(p._name), _age(p._age){}Person& operator=(const Person& p){if (this != &p){_name = p._name;_age = p._age;}return *this;}// 强制生成移动构造和移动赋值Person(Person&& p) = default;Person& operator=(Person&& p) = default;//不想生产(让Person对象拷贝)Person(const Person& p) = delete;~Person(){cout << "~Person()" << endl;}private:bit::string _name; // 自定义类型int _age = 1;		   // 内置类型};int main(){Person s1("张三", 18);Person s2 = s1;Person s3 = std::move(s1);cout << endl << endl;Person s4;s4 = std::move(s2);return 0;}

final || override

在C++中,finaloverride是两个关键字,用于对类的成员函数进行修饰和控制。

  1. final关键字:final用于修饰类、虚函数和成员函数,表示它们不能被继承、重写或覆盖。当一个类被声明为final时,其他类就不能从该类派生。当一个虚函数被声明为final时,它不能在派生类中被重写或覆盖。当一个非虚函数被声明为final时,它不能在派生类中被重新定义。
class Base final {// ...
};class Derived : public Base {  // 错误,Base类被声明为final,不能被继承// ...
};class Base {
public:virtual void foo() final {// ...}
};class Derived : public Base {
public:void foo() override {  // 错误,foo函数被声明为final,不能被重写// ...}
};
  1. override关键字:override用于修饰派生类中的虚函数,表示该函数是对基类中的虚函数的重写。使用override可以提高代码的可读性和安全性,确保派生类中的函数与基类中的虚函数具有相同的签名。
class Base {
public:virtual void foo() {// ...}
};class Derived : public Base {
public:void foo() override {  // 明确标记为重写虚函数// ...}
};

如果在派生类中使用了override关键字修饰一个函数,但该函数并不是基类中的虚函数,编译器将会报错。

总之,finaloverride是C++11引入的关键字,用于对类的成员函数进行修饰和控制。final表示类或函数不能被继承、重写或覆盖,而override表示派生类中的函数是对基类中虚函数的重写。

要求delete关键字实现,一个类,只能在堆上创建对象

当构造函数被声明为私有时,它只能在类的内部被访问。这意味着在类的外部无法直接调用构造函数来创建对象。因此,将构造函数设为私有可以阻止类在栈上创建对象的方式。

在C++中,当你在栈上声明一个对象时,编译器会在编译时自动调用类的构造函数来创建对象。但是,如果构造函数是私有的,编译器将无法调用该构造函数,从而阻止了在栈上创建对象的方式。

以下是一个示例代码,展示了私有构造函数如何阻止类在栈上创建对象的方式:

class MyClass {
private:MyClass() {}  // 私有的构造函数public:void doSomething() {// 对象的成员函数}
};int main() {MyClass obj;  // 编译错误!无法调用私有构造函数return 0;
}

在上面的示例中,我们将构造函数声明为私有的,然后在main()函数中尝试在栈上创建一个MyClass对象。由于构造函数是私有的,编译器将无法调用该构造函数,从而导致编译错误。

需要注意的是,尽管无法在栈上直接创建对象,但仍然可以通过其他方式(如静态成员函数或友元函数)在堆上创建对象。

class HeapOnly
{
public:~HeapOnly() = delete;
};
int main()
{//HeapOnly hp1;//static HeapOnly hp2;          //自定义类型会调用析构HeapOnly* ptr = new HeapOnly;  //指针不会调用析构return 0;
}

下面例子此时会有资源泄露

class HeapOnly
{
public:HeapOnly(){_str = new char[10];}~HeapOnly() = delete;
private:char* _str;
};
int main()
{//HeapOnly hp1;//static HeapOnly hp2;          //自定义类型会调用析构HeapOnly* ptr = new HeapOnly;  //指针不会调用析构//delete ptr;                  //无析构 不能deletereturn 0;
}

自写destroy解决

// 要求delete关键字实现,一个类,只能在堆上创建对象
class HeapOnly
{
public:HeapOnly(){_str = new char[10];}~HeapOnly() = delete;void Destroy(){delete[] _str; operator delete(this);}
private:char* _str;
};
int main()
{//HeapOnly hp1;//static HeapOnly hp2;          //自定义类型会调用析构HeapOnly* ptr = new HeapOnly;  //指针不会调用析构//delete ptr;                  //无析构 不能deleteptr->Destroy();return 0;
}

可变参数模板

在这里插入图片描述

//可变参数的函数模板
template <class ...Args>
void ShowList(Args... args)
{cout<< sizeof...(args) <<endl;  //计算几个参数
}
int main()
{string str("hello");ShowList(1);ShowList();ShowList(1, 2);ShowList(1, 'A', str);return 0;
}

在这里插入图片描述
递归看参数

//可变参数的函数模板
void ShowList()
{cout << endl;
}template <class T, class ...Args>
void ShowList(const T& val, Args... args)
{cout << val << " ";ShowList(args...);//cout<< sizeof...(args) <<endl;
}
int main()
{string str("hello");ShowList(1);ShowList();ShowList(1, 2);ShowList(1, 'A', str);return 0;
}

结果

11 2
1 A hello

列表初始化获取

template<class T>
int PrintArg(const T& x)
{cout << x << " ";return 0; 
}
template <class ...Args>
void ShowList(Args... args)
{int a[] = { PrintArg(args)... };cout << endl;
}
int main()
{string str("hello");ShowList(1);ShowList();ShowList(1, 2);ShowList(1, 'A', str);return 0;
}

emplace

emplace_back()是C++标准库容器(如vector、list和deque)提供的一个成员函数,用于在容器的末尾直接构造对象,而不需要显式地调用构造函数。

emplace_back()的优势主要体现在以下几个方面:

  1. 减少对象的拷贝或移动:使用emplace_back()可以直接在容器的末尾构造对象,而不需要先创建一个临时对象,然后再将其拷贝或移动到容器中。这样可以减少不必要的对象拷贝或移动操作,提高代码效率。

  2. 简化代码:相比于显式地调用构造函数和push_back()函数,使用emplace_back()可以更简洁地创建对象并将其添加到容器中。你只需要传递构造函数所需的参数,而不需要创建临时对象或手动调用构造函数。

  3. 支持完美转发:emplace_back()函数支持完美转发,可以将参数直接传递给构造函数,无需手动进行类型转换。这意味着你可以使用不同类型的参数来构造对象,而不需要为每个类型编写重载的构造函数。

以下是一个使用emplace_back()的示例代码:

#include <vector>class MyClass {
public:MyClass(int x, int y) {// 构造函数的实现}
};int main() {std::vector<MyClass> myVector;myVector.emplace_back(10, 20);  // 在容器的末尾构造对象return 0;
}

在上面的示例中,我们使用emplace_back()函数在myVector容器的末尾直接构造了一个MyClass对象,而不需要先创建一个临时对象。

总而言之,emplace_back()函数可以提高代码的效率和可读性,减少对象的拷贝或移动,并支持完美转发,使代码更加简洁和灵活。

emplace支持参数包
在这里插入图片描述

定位new

内存池 显示的调用构造函数

lambda

在这里插入图片描述
在这里插入图片描述
简单的lambda函数

int mian()
{//两个数相加的lambdaauto add1 = [](int a, int b)->int{return a + b; };cout << add1(1, 2) << endl;//省略返回值auto add2 = [](int a, int b){return a + b; };cout << add2(1, 2) << endl;//交换变量的lambdaint x = 0,  y = 1;auto swap1 = [](int& x1, int& x2)->void {int tmp = x1; x1 = x2; x2 = tmp; };swap1(x, y);cout << x << ":" << y << endl;auto swap2 = [](int& x1, int& x2){int tmp = x1; x1 = x2; x2 = tmp; };swap2(x, y);cout << x << ":" << y << endl;//不传参数交换x,y  lambda  --捕捉列表  (默认捕捉过来的变量不能修改 加mutable)//auto swap3 = [x, y]()mutable   //无修改作用auto swap3 = [&x, &y]()   //传引用捕捉{int tmp = x;x = y;y = tmp;};swap3();cout << x << ":" << y << endl;return 0;
}

lambda作为sort的参数(之前用反函数对象或者类型实现)

	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._name <g2._name; });

相关文章:

c++(强生成关键字+可变参数模板+emplace)[26]

强制生成 不生成 在C中&#xff0c;可以通过一些方式来控制编译器是否生成某些特殊成员函数&#xff08;如默认构造函数、拷贝构造函数、拷贝赋值运算符、析构函数等&#xff09;。 默认生成&#xff1a;如果你没有显式地定义这些特殊成员函数&#xff0c;编译器会自动生成它们…...

Mysql 数据库开发及企业级应用

文章目录 1、Mysql 数据库开发及企业级应用1.1、为什么要使用数据库1.1.1、数据库概念&#xff08;Database&#xff09;1.1.2、为什么需要数据库 1.2、程序员为什么要学习数据库1.3、数据库的选择1.3.1、主流数据库简介1.3.2、使用 MySQL 的优势1.3.3、版本选择 1.4、Windows …...

【数据结构】_6.队列

目录 1.概念 2.队列的使用 3.队列模拟实现 4.循环队列 5.双端队列 6.OJ题 6.1 用队列实现栈 6.2 用栈实现队列 1.概念 &#xff08;1&#xff09;队列是只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff1b; &#xff08;2&am…...

7 网络通信(上)

文章目录 网络通信概述ip地址ip的作用ip地址的分类私有ip 掩码和广播地址 linux 命令&#xff08;ping ifconfig&#xff09;查看或配置网卡信息&#xff1a;ifconfig(widows 用ipconfig)测试远程主机连通性&#xff1a;ping路由查看 端口端口是怎样分配的知名端口动态端口 查看…...

MFC图表控件high-speed-charting的使用

high-speed-charting是MFC上的开源图表库,Teechart的替代品。 high-speed-charting的下载地址 https://www.codeproject.com/Articles/14075/High-speed-Charting-Control 特性 High-speed drawing (when axis is fixed) which allows fast plotting of dataUnlimited number …...

Unity中常用方法

1.基础 //初始化引入 [RequireComponent(typeof(BoxCollider2D))] [RequireComponent(typeof(Rigidbody2D))]//游戏帧率设置 60帧Application.targetFrameRate 60;//获取物体对象 //获取到当前物体(根据名称&#xff0c;也可以根据路径)GameObject go GameObject.Find("…...

【监控系统】可视化工具Grafana简介及容器化部署实战

1.什么是Grafana 官网地址&#xff1a;https://grafana.com/ Grafana用Go语言开发的开源数据可视化工具&#xff0c;可以做数据监控和数据统计&#xff0c;带有告警功能。支持快速灵活的客户端图表&#xff0c;面板插件有许多不同方式的可视化指标和日志&#xff0c;官方库中…...

VUE之VueRouter页面跳转

参考资料&#xff1a; 参考视频 参考demo及视频资料 VUE之基本部署及VScode常用插件 VUE之基本组成和使用 VUE之Bootstrap和Element-UI的使用 VUE之axios使用&#xff0c;跨域问题&#xff0c;拦截器添加Token Vue Router官网 Vue Router说明&#xff1a; 说明&#xf…...

【188】Java8利用AVL树实现Map

AVL树又被叫做平衡二叉搜索树、平衡二叉树。AVL是其发明者的首字母缩写。 这篇文章中&#xff0c;AVLTreeMap 类集成了 java.util.Map 接口&#xff0c;并利用 AVL 树结构实现了 Map 接口的所有方法。本文还给出了测试代码。 为什么要发明AVL树&#xff1f; 当我按照从小到大…...

[SQL挖掘机] - 右连接: right join

介绍: 右连接是一种多表连接方式&#xff0c;它以右侧的表为基础&#xff0c;并返回满足连接条件的匹配行以及右侧表中的所有行&#xff0c;即使左侧的表中没有匹配的行。右连接将右表的每一行与左表进行比较&#xff0c;并根据连接条件返回结果集。其实, 左连接和右连接原理一…...

bug篇之基于docker安装nacos(2.1.1)使用dubbo连接不上的问题

说明&#xff1a;首先我的nacos安装是2.1.1版本&#xff0c;请注意版本问题。另外启动时用dubbo的话必须先启动服务提供者再启动服务使用者&#xff0c;否则会报错&#xff0c;同时也必须开放三个端口&#xff1a;8848&#xff0c;9848&#xff0c;9849 java.lang.IllegalStat…...

【Python入门系列】第二十一篇:Python物联网和传感器应用

文章目录 前言一、Python在物联网和传感器应用中的优势二、连接传感器和设备三、读取传感器数据四、示例代码和讲解五、进一步处理和分析传感器数据六、更多应用示例1、温湿度监测系统2、智能家居系统 - 灯光控制 总结 前言 物联网和传感器在现代科技中扮演着重要的角色。物联…...

Python爬虫的urlib的学习(学习于b站尚硅谷)

目录 一、页面结构的介绍  1.学习目标  2.为什么要了解页面&#xff08;html&#xff09;  3. html中的标签&#xff08;仅介绍了含表格、无序列表、有序列表、超链接&#xff09;  4.本节的演示 二、Urllib  1.什么是互联网爬虫&#xff1f;  2.爬虫核心  3.爬虫…...

【MongoDB】--MongoDB聚合Aggregation

目录 一、前言二、聚合管道操作2.1、实际案例1(1)、案例--根据学生no&#xff0c;找到对应班级名称(2)、案例--这个班级有哪些学生和哪些老师在任课 2.2、实际案例2(1)、案例--主表和关联表都有条件限制&#xff0c;且分页返回 一、前言 聚合操作组值来自多个文档&#xff0c;…...

Hadoop学习指南:探索大数据时代的重要组成——Hadoop概述

前言 在当今大数据时代&#xff0c;处理海量数据成为了一项关键任务。Hadoop作为一种开源的分布式计算框架&#xff0c;为大规模数据处理和存储提供了强大的解决方案。本文将介绍Hadoop的组成和其在大数据处理中的重要作用&#xff0c;让我们一同踏上学习Hadoop的旅程。 Hado…...

Java实现简单小画板

Java制作简单画板&#xff0c;包括两个类&#xff0c;一个主要画板类Drawpad&#xff0c;一个画板监听器DrawListener类。 1、Drawpad类&#xff0c;包括画板&#xff0c;画板功能设计&#xff0c;保存图片等 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2…...

B078-项目实战--支付模块 领养订单支付流程

目录 支付模块需求分析表设计支付单表支付宝账号信息表-商家账号微信支付账号信息表-商家账号银行账号表-商家资金账号表支付流水表 流程分析支付基础模块继承加密算法沙箱环境准备支付宝支付-流程分析根据demo封装工具类导入依赖AlipayConfigAlipayInfoAlipayUtil 内网穿透 领…...

[css]margin-top不起作用问题(外边距合并)

在初学css时&#xff0c;会遇到突然间margin-top不起作用的情况。如下面&#xff1a; 情况一&#xff1a; 代码&#xff1a; <html> <head><style type"text/css"> * {margin:0;padding:0;border:0; }#outer {width:300px;height:300px;backgroun…...

Vue2基础八、插槽

零、文章目录 Vue2基础八、插槽 1、插槽 &#xff08;1&#xff09;默认插槽 作用&#xff1a;让组件内部的一些 结构 支持 自定义需求: 将需要多次显示的对话框, 封装成一个组件问题&#xff1a;组件的内容部分&#xff0c;不希望写死&#xff0c;希望能使用的时候自定义。…...

自然语言处理从入门到应用——LangChain:提示(Prompts)-[提示模板:连接到特征存储]

分类目录&#xff1a;《自然语言处理从入门到应用》总目录 特征存储是传统机器学习中的一个概念&#xff0c;它确保输入模型的数据是最新和相关的。在考虑将LLM应用程序投入生产时&#xff0c;这个概念非常重要。为了个性化LLM应用程序&#xff0c;我们可能希望将LLM与特定用户…...

jenkins自定义邮件发送人姓名

jenkins发送邮件的时候发送人姓名默认的&#xff0c;如果要自定义发件人姓名&#xff0c;只需要修改如下信息即可&#xff1a; 系统管理-system-Jenkins Location下的系统管理员邮件地址 格式为&#xff1a;自定义姓名<邮件地址>...

SolidWorks二次开发---简单的连接solidworks

创建一个.net Framework的应用&#xff0c;正常4.0以上就可以了。 打开nuget包管理 在里面搜索paine 在版中选择对应的solidworks年份开头的&#xff0c;进行安装。 安装完之后 : 同时选中下面两个dll,把嵌入操作类型改为false 然后在按钮的单击事件中输入: Connect.Crea…...

docker 安装 active Mq

在安装完Docker的机器上&#xff0c;安装activeMQ。 拉取镜像&#xff1a; docker pull webcenter/activemq 查看镜像&#xff1a; docker images Docker运行ActiveMQ镜像 docker run --name activemq -d -p 8161:8161 -p 61616:61616 --privilegedtrue --restartalways …...

【Linux】TCP协议

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《学会Linux》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录 &#x1f449;TCP协议&…...

DevOps系列文章之 自动化测试大全(单测和集成测试)

自动化测试业界主流工具 核心目标&#xff1a; 主要是功能测试和覆盖率测试 业界常用主流工具 GoogleTest GoogleTest是一个跨平台的(Liunx、Mac OS X、Windows 、Cygwin 、Windows CE and Symbian ) C单元测试框架&#xff0c;由google公司发布&#xff0c;为在不同平台上为编…...

Android启动速度优化

本节主要内容&#xff1a;了解APP启动流程、启动状态、查看启动时间、CPU Profile定位启动耗时代码、StrictMode严苛模式检测不合理写法、解决启动黑白屏问题。 一、APP启动流程 ①用户点击桌面App图标&#xff0c;Launcher进程采用Binder IPC向system_server进程发起startAc…...

linux 日志 系统安全日志 web日志

web日志 LINUX日志系统之WEB日志&#xff08;一&#xff09;_dracut.log_麻子来了的博客-CSDN博客 系统安全日志 Linux系统安全日志详解_sinolover的博客-CSDN博客 wtmp和utmp文件都是二进制文件&#xff0c;需使用who、w、users、last和ac来操作这两个文件。 who /var/lo…...

SpringBoot 整合 MongoDB 连接 阿里云MongoDB

注&#xff1a;spring-boot-starter-data-mongodb 2.7.5&#xff1b;jdk 1.8 阿里云MongoDB是副本集实例的 在网上查找了一番&#xff0c;大多数都是教连接本地mongodb或者linux上的mongodb 阿里云上有java版连接教程&#xff0c;但它不是SpringBoot方法配置的&#xff0c;是手…...

Debeizum 增量快照

在Debeizum1.6版本发布之后&#xff0c;成功推出了Incremental Snapshot&#xff08;增量快照&#xff09;的功能&#xff0c;同时取代了原有的实验性的Parallel Snapshot&#xff08;并行快照&#xff09;。在本篇博客中&#xff0c;我将介绍全新快照方式的原理&#xff0c;以…...

windows下安装composer

安装Php 教程 下载composer 官网 中文网站 exe下载地址 下载好exe 双击运行 找到php.ini注释一行代码 测试 composer -v说明安装成功 修改源 执行以下命令即可修改 composer config -g repo.packagist composer https://packagist.phpcomposer.com # 查看配置…...