C++11:可变参数模板 emplace_back

news2024/12/25 9:21:46

可变参数模板

基本概念:C++ 的参数模板是 C++11 引入的特性,它允许模板接受可变数量的参数

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args... args,这个参数包中可以包含0到N个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}

emplace_back 

基本概念:emplace_back是C++11提供的一个基于可变参数模板实现的新的成员函数

我们用下面这段代码来尝试一下emplace_back和push_back的区别:

///验证深拷贝
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

#include<vector>
#include<list>
#include<map>
#include<set>
#include<string>

#include<assert.h>

namespace bit
{
	class string
	{
	public:
		typedef char* iterator;
		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		string(const char* str = "")
			:_size(strlen(str))
			, _capacity(_size)
		{
			cout << "string(char* str)" << endl;

			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		// s1.swap(s2)
		void swap(string& s)
		{
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity, s._capacity);
		}

		// 拷贝构造 -- 左值
		string(const string& s)
			:_str(nullptr)
		{
			cout << "string(const string& s) -- 深拷贝" << endl;

			_str = new char[s._capacity + 1];
			strcpy(_str, s._str);
			_size = s._size;
			_capacity = s._capacity;
		}

		// 移动构造 -- 右值(将亡值)
		string(string&& s)
		{
			cout << "string(string&& s) -- 移动拷贝" << endl;
			swap(s);
		}

		// 拷贝赋值
		// s2 = tmp
		string& operator=(const string& s)
		{
			cout << "string& operator=(const string& s) -- 深拷贝" << endl;
			string tmp(s);
			swap(tmp);

			return *this;
		}

		// 移动赋值
		string& operator=(string&& s)
		{
			cout << "string& operator=(string&& s) -- 移动拷贝" << endl;
			swap(s);

			return *this;
		}

		~string()
		{
			delete[] _str;
			_str = nullptr;
		}

		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}

		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;

				_capacity = n;
			}
		}

		void push_back(char ch)
		{
			if (_size >= _capacity)
			{
				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newcapacity);
			}

			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}

		//string operator+=(char ch)
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}

		const char* c_str() const
		{
			return _str;
		}
	private:
		char* _str = nullptr;
		size_t _size = 0;
		size_t _capacity = 0; // 不包含最后做标识的\0
	};

	bit::string to_string(int value)
	{
		bool flag = true;
		if (value < 0)
		{
			flag = false;
			value = 0 - value;
		}

		bit::string str;
		while (value > 0)
		{
			int x = value % 10;
			value /= 10;
			str += ('0' + x);
		}
		if (flag == false)
		{
			str += '-';
		}

		std::reverse(str.begin(), str.end());
		return str;
	}
}
int main()
{
	std::list<bit::string> lt1;

	bit::string s1("xxxx");
	lt1.push_back(s1);
	lt1.push_back(move(s1));
	cout << "=============================================" << endl;

	bit::string s2("xxxx");
	lt1.emplace_back(s2);
	lt1.emplace_back(move(s2));
	cout << "=============================================" << endl;

	lt1.push_back("xxxx");
	lt1.emplace_back("xxxx");
	cout << "=============================================" << endl;

	std::list<pair<bit::string, bit::string>> lt2;
	pair<bit::string, bit::string> kv1("xxxx", "yyyy");
	lt2.push_back(kv1);
	lt2.push_back(move(kv1));
	cout << "=============================================" << endl;

	pair<bit::string, bit::string> kv2("xxxx", "yyyy");
	lt2.emplace_back(kv2);
	lt2.emplace_back(move(kv2));
	cout << "=============================================" << endl;

	lt2.emplace_back("xxxx", "yyyy");
	cout << "=============================================" << endl;


	return 0;
}

验证浅拷贝
class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date(int year, int month, int day)" << endl;
	}

	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		cout << "Date(const Date& d)" << endl;
	}
private:
	int _year = 1;
	int _month = 1;
	int _day = 1;
};

int main()
{
	std::list<Date> lt1;
	lt1.push_back({ 2024,3,30 });

	// 不支持
	//lt1.emplace_back({ 2024,3,30 });

	// 推荐
	lt1.emplace_back(2024, 3, 30);

	cout << endl;
	Date d1(2023, 1, 1);
	lt1.push_back(d1);
	lt1.emplace_back(d1);

	cout << endl;
	lt1.push_back(Date(2023, 1, 1));
	lt1.emplace_back(Date(2023, 1, 1));


	return 0;
}

结论:

1、对于插入单个对象而言,emplace_back和push_back没有区别

2、对于需要深拷贝的类对象,emplace_back可以减少一次移动构造

3、对于需要浅拷贝的类对象,emplace_back可以减少一次拷贝构造

4、emplace_back不支持使用{}传参

5、emplace_back可以用于尾插不支持拷贝构造的自定义类(由3推出)

~over~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue21-列表排序

一、需求 二、解决方式 <body><div id"root"><h2>人员列表</h2><input type"text" placeholder"请输入" v-model"keyword"><button click"sortType 1">年龄升序</button><b…

uniapp地图导航

我们只需要给图标加一个点击事件 我这里的数据都是动态的&#xff0c;想测试的朋友可以写固定值 然后跳转之后首先会调到选择软件导航 点击导航之后会显示使用哪个app 最后我们选择之后将会直接跳转到app进行导航

spring boot3登录开发-邮件验证码接口实现

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 目录 写在前面 上文衔接 接口设计与实现 1.接口分析 2.实现思路 3.代码实现 1.定义验证码短信HTML模板枚举类 2.定义验证码业务接口 3. 验证码业务接口实现 4.控制层代码 4.测试 写…

带你走进信息安全软件架构

汽车行业网联化以及网络安全风险日益突出&#xff0c;汽车网络攻击&#xff0c;漏洞日益增加&#xff0c;危害防不胜防。汽车信息安全逐步受到重视&#xff0c;网络安全相关法律法规陆续颁布。在这样的背景下&#xff0c;AUTOSAR 组织也发布了有关信息安全模块和 Crypto Stack(…

【ARM Coresight Debug 系列 -- ARMv8/v9 软件实现断点地址设置】

请阅读【嵌入式开发学习必备专栏 】 文章目录 ARMv8/v9 软件设置断点地址断点地址软件配置流程代码实现 ARMv8/v9 软件设置断点地址 在ARMv8/9架构中&#xff0c;可以通过寄存器 DBGBVR0_EL1 设置断点。这个寄存器是一系列调试断点值寄存器中的第一个DBGBVRn_EL1&#xff0c;其…

Chromium源码阅读:深入理解Mojo框架的设计思想,并掌握其基本用法(1)

Mojo简介 Mojo 是一个运行时库的集合&#xff0c;提供与平台无关的通用 IPC 原语抽象、消息 IDL 格式以及具有针对多种目标语言的代码生成的绑定库&#xff0c;以便于跨任意进程间和进程内边界传递消息。 Mojo 分为清晰分离的层&#xff0c;子组件的基本层次结构如下&#xff…

GraphQL(7):ConstructingTypes

1 使用GraphQLObjectType 定义type&#xff08;类型&#xff09; 不使用ConstructingTypes定义方式如下&#xff1a; 使用ConstructingTypes定义方式如下&#xff1a; 更接近于构造函数方式 var AccountType new graphql.GraphQLObjectType({name: Account,fields: {name: …

微软Win10 21H2/22H2六月更新补丁KB5039211来了!附完整更新日志

系统之家于6月12日发出最新报道&#xff0c;微软为 Windows 10 用户发布了六月的安全更新补丁KB5039211。对于 21H2 版本的用户&#xff0c;系统版本号将升级至 19044.4529&#xff1b;而对于 22H2 版本&#xff0c;版本号则提升至 19045.4529。此次更新的亮点在于增强了系统的…

批量放大PNG图片至指定像素,画质优先,轻松提升图片品质与视觉体验!

在数字化时代&#xff0c;图片已经成为我们生活和工作中不可或缺的一部分。然而&#xff0c;很多时候我们面临着这样的问题&#xff1a;手头的Png图片尺寸太小&#xff0c;无法满足我们的需求&#xff1b;或者想要将图片放大&#xff0c;却又担心画质受损。别担心&#xff0c;现…

深度学习实战79-ChatTTS实现有感情有笑声的语音,无法分辨是人还是机器的语音

大家好,我是微学AI,今天给大介绍一下深度学习实战79-ChatTTS实现有感情有笑声的语音,本地部署运行,难以分辨是人还是机器的语音。ChatTTS是文本转语音模型,例如LLM助手对话任务。它支持英文和中文两种语言。ChatTTS模型代码已经开源,但是很多人启动不起来,会遇到各种的问…

R可视化:R语言基础图形合集

R语言基础图形合集 欢迎大家关注全网生信学习者系列&#xff1a; WX公zhong号&#xff1a;生信学习者Xiao hong书&#xff1a;生信学习者知hu&#xff1a;生信学习者CDSN&#xff1a;生信学习者2 基础图形可视化 数据分析的图形可视化是了解数据分布、波动和相关性等属性必…

深入浅出通信原理 | 通信系统中的性能指标评估

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 本节目录 一、通信系统中的性能指…

数据结构与算法笔记:基础篇 -递归树:如何借助树来求解递归算法的时间复杂度?

概述 我们都知道&#xff0c;递归代码的时间复杂度分析起来很麻烦。在《排序(下)》哪里讲过&#xff0c;如何用递推公式&#xff0c;求解归并排序、快速排序的时间复杂度&#xff0c;但是有些情况&#xff0c;比如快排的平均时间复杂度的分析&#xff0c;用递推公式的话&#…

远程主机强迫关闭了一个现有的连接redis

引言 在使用 Redis 进行开发和运维过程中&#xff0c;我们可能会遇到 Redis 连接被远程主机强制关闭的情况。本文将介绍造成这种情况的原因&#xff0c;并给出一些处理方法和建议。 远程主机强制关闭连接的原因 远程主机强制关闭连接通常是由于网络不稳定、连接超时、Redis 配…

Linux网络 - HTTP协议

文章目录 前言一、HTTP协议1.urlurl特殊字符 requestrespond 总结 前言 上一章内容我们讲了在应用层制定了我们自己自定义的协议、序列化和反序列化。 协议的制定相对来讲还是比较麻烦的&#xff0c;不过既然应用层的协议制定是必要的&#xff0c;那么肯定已经有许多计算机大佬…

看国足!不破不立!层次越低的家庭,语言攻击性越强——早读(逆天打工人爬取热门微信文章解读)

你昨晚看国足了吗&#xff1f; 引言Python 代码第一篇 洞见 层次越低的家庭&#xff0c;语言攻击性越强第二篇结尾 引言 昨天看了国足比赛 输了韩国一个球 剩下大概率的出线希望 除非泰国赢新加坡 且3个球或者以上 泰国稍强于新加坡 但并不到打进3个球的地步 都觉得2个球已经是…

每日5题Day22 - LeetCode 106 - 110

每一步向前都是向自己的梦想更近一步&#xff0c;坚持不懈&#xff0c;勇往直前&#xff01; 第一题&#xff1a;106. 从中序与后序遍历序列构造二叉树 - 力扣&#xff08;LeetCode&#xff09; class Solution {public TreeNode buildTree(int[] inorder, int[] postorder) {…

质数(素数)的几种判断方法

判断一个数是否为质数/合数是在数据处理中经常遇到的问题&#xff0c;如何解决这个问题&#xff0c;作者总结了如下几种算法。 质数的定义&#xff1a; 一个数如果除了1 和 其本身外&#xff0c;不能被其它数整除&#xff0c;就称这个数为质数&#xff08;或素数&#xff09;…

【计算机体系结构复习】

一.选择题&#xff08;2 X 15) 第五章第六章没有 第一章 第二章 第三章 第四章 第七章 第八章 二.主观题 第一章 1.7 1.11 怎么计算程序执行时间CPI、MIPS CPI变化&#xff0c;系统性能怎么变&#xff08;上课例子&#xff09; p9 例1.3 第二章 哈夫曼…

CVE-2012-2122-mysql未授权访问漏洞复现-vulhub

1.原理 参考&#xff1a;CVE-2012-2122 Mysql身份认证漏洞及利用-CSDN博客 简单来说&#xff0c;除了配置上的问题以外&#xff0c;是密码的验证出现了漏洞&#xff0c;导致尝试次数多了之后直接可以登入 使用&#xff1a;kalivulhub 2.复现 开一下镜像&#xff0c;用的是v…