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

Boost开发指南-4.5swap

swap

boost::swap是对标准库里的std::swap 的增强和泛化,为交换两个变量(可以是int等内置数据类型,或者是类实例、容器)的值提供了便捷的方法。

为了使用boost::swap,需要包含头文件<boost/swap.hpp>,即

#include<boost/swap.hpp>

原理

C++98标准中的std::swap()

template<typename T>
void swap(T&a, T& b)
{T tmp(a);a = b;b = temp;
}

从代码中可以看出,std::swap()要求交换的对象必须是可拷贝构造和可拷贝赋值的,它提供的是最通用同时也是效率最低的方法,需要进行一次复制构造和两次赋值操作,如果交换的对象很大,那么运行代价会相当昂贵。

C++11标准中使用转移语义对std::swap()进行了优化,避免了拷贝的代价。

template<typename T>
void swap(T& a, T& b)
{T tmp = std::move(a); //move, 把a偷到tmpa = std::move(b); //move, 把b偷到ab = std::move(tmp); //move, 把tmp偷到b
}

但不是所有的类都实现了自己的转移构造和赋值函数的,而且编译器的支持也是个必须考虑的问题,所以对于我们自己写的类,最好能够实现优化的swap()来提高效率。

解决方案有两种:第一种方案是直接利用函数重载,编写一个同名的 swap_函数,这个swap()再调用类内部的高效成员交换函数,这样编译器在编译时就不会使用std::swap()。第二种方案是使用ADrR查找模板特化的 std::swap。这两种方案就是 boost::swap的工作原理。

boost::swap查找有无针对类型T的std::swap()的特化或者通过ADL查找模板特化的 swap(),如果有则调用,如果两种查找都失败时则退化为std::swap()。此外,boost::swap还增加了一个很实用的功能——对C++内建数组交换的支持(已经被收入C++11标准)。

boost::swap()函数的声明是:

template<class T1, class T2>
void swap(T1& left, T2& right);

由于boost::swap()与std::swap()同名,所以我们不能使用using语句打开boost名字空间,应该总以boost名字空间限定的方式调用它。

交换数组

boost::swap可以直接交换两个数组的内容,但要求参与交换的两个数组必须具有相同的长度。下面的代码使用标准库算法 fill_n 将两个数组分别赋值为5和20,然后调用boost::swap()交换:

int a1[10]; //两个数组
int a2[10];std::fill_n(a1, 10, 5); //fill_n赋初始值
std::fill_n(a2, 10, 20);boost::swap(a1, a2); //交换两个数组的内容

boost::swap交换数组内容的实现很简单,它使用了一个for循环,对数组中的每个元素调用单个元素版的boost::swap完成整个数组内容的交换。在上面的代码执行后a1中元素的值将为20,而a2中元素的值将为5。

如果企图用boost::swap 交换两个长度不相同的数组,那么将无法通过编译:

int a1[10], a2[12]; //两个长度不相同的数组
boost::swap(a1, a2); //发生编译错误

特化std::swap

接下来我们用一个简单的三维空间的点 point 作为例子,示范模板特化的方法使用boost::swap。它实现了内部高效的交换函数:

class point
{int x, y, z;
public:explicit point(int a = 0, int b = 0, int c = 0) :x(a), y(b), z(c) {}void print()const{cout << x << "," << y << "," << z << endl;}void swap(point& p) //内置高效交换函数{std::swap(x, p.x);std::swap(y, p.y);std::swap(z, p.z);cout << "inner swap" << endl;}
};

特化std::swap()的方法需要向std名字空间添加自定义函数:

namespace std
{template<>void swap(point &x, point &y){ x.swap(y); }
}int main()
{point a(1,2,3), b(4,5,6);cout << "std::swap" << endl;std::swap(a,b); //调用std::swapcout << "boost::swap" << endl;boost::swap(a, b); //调用boost::swap
}

由于我们在名字空间特化了std::swap,因此,boost::swap与std::swap的效果相同,都使用了特化后的swap函数。

特化ADL可找到的swap

依然使用刚才的point类,但这次我们不变动std名字空间,而是在全局域实现swap函数:

void swap(point &x, point &y) //全局域的swap函数
{ x.swap(y); }int main()
{point a(1,2,3), b(4,5,6);cout << "std::swap" << endl;std::swap(a,b); //调用std::swapcout << "boost::swap" << endl;boost::swap(a,b); //调用boost::swap
}

这段代码的运行结果与之前的特化std::swap有明显不同,std::swap使用了标准的交换操作,而 boost::swap通过ADL 规则找到了全局名字空间的特化交换函数,实现了高效的交换。

如果读者担心在全局名字空间编写自由函数 swap 会造成名字“污染”,则可以把特化的swap加入到boost名字空间,或者其他ADL可以找到的名字空间。

代码示例

#include <iostream>
using namespace std;#include <boost/core/swap.hpp>
#include <boost/assign.hpp>//
void case1()
{using namespace boost::assign;int a1[10];int a2[10];std::fill_n(a1, 10, 5);std::fill_n(a2, 10, 20);boost::swap(a1, a2);}//
class point
{int x, y, z;
public:explicit point(int a = 0, int b = 0, int c = 0) :x(a), y(b), z(c) {}void print()const{cout << x << "," << y << "," << z << endl;}void swap(point& p){std::swap(x, p.x);std::swap(y, p.y);std::swap(z, p.z);cout << "inner swap" << endl;}
};//namespace std
//{
//template<>
//void swap(point &x, point &y)               //模板特化swap函数
//{   x.swap(y);}
//}namespace boost {void swap(point& x, point& y){x.swap(y);}
}void case2()
{point a(1, 2, 3), b(4, 5, 6);cout << "std::swap" << endl;std::swap(a, b);cout << "boost::swap" << endl;boost::swap(a, b);
}//int main()
{case1();case2();
}

相关文章:

Boost开发指南-4.5swap

swap boost::swap是对标准库里的std::swap 的增强和泛化&#xff0c;为交换两个变量&#xff08;可以是int等内置数据类型&#xff0c;或者是类实例、容器&#xff09;的值提供了便捷的方法。 为了使用boost::swap&#xff0c;需要包含头文件<boost/swap.hpp>&#xff…...

OpenStack对接Ceph平台

OpenStack对接Ceph平台 目录 OpenStack对接Ceph平台 1、创建后端需要的存储池(ceph-01节点操作)2、创建后端用户 2.1 创建密钥(ceph-01节点操作) 2.1.1 创建用户client.cinder2.1.2 创建用户client.glance2.1.3 创建用户client.cinder-backup2.2 导出密钥(ceph-01节点操作)2.3 …...

【Vue2】动态组件的使用-切换组件和keep-alive,以及异步组件

目录 想实现切换不同列表展示不同数据方法一方法二&#xff0c;动态组件动态组件的父组件如何传的值动态组件的子组件如何接受传的值 认识keep-alive缓存组件的生命周期 异步组件&#xff0c;单独打包&#xff0c;实现webpack分包&#xff0c;如何对组件进行单独打包&#xff0…...

C++的IO流

目录 C语言的输入与输出 流是什么 CIO流 C标准IO流 C文件IO流 stringstream的简单介绍 在C语言中&#xff0c;如果想要将一个整形变量的数据转化为字符串格式&#xff0c;如何去做&#xff1f; 将数值类型数据格式化为字符串 字符串拼接 序列化和反序列化结构数据 注…...

nodejs+vue+elementui电影订票网站系统_wqc3k

电影订票系统在国内有很多值得借鉴的例子&#xff0c;功能也都趋于完善&#xff0c;因此此次电影订票系统将轻量化开发&#xff0c;要完成以下功能&#xff1a; &#xff08;1&#xff09;要支持完整的用户注册&#xff0c;登录功能&#xff0c;账号的管理通过管理员来实现。 &…...

2023-08-14 linux 串口终端输入长命令不换行,覆盖前面内容,stty命令设置串口终端行列数

一、linux 串口终端输入长命令不换行&#xff0c;覆盖前面内容&#xff0c;现象如下图&#xff1a; 二、解决方法&#xff1a;用stty 命令设置行列数 stty columns 200 stty rows 10三、参考文章 https://www.cnblogs.com/goloving/p/15170537.html 常用Linux串口设备操作命…...

根据指定日期获取周,月,季度,年的第一天和最后一天

1. 根据指定日期获取周&#xff0c;月&#xff0c;季度&#xff0c;年的第一天和最后一天 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date;/*** 根据给定时间获取周、月度、季度、年度开始结束时间*…...

CRMEB商城系统:便捷、安全、多样化的购物方式

商城系统是当今社会商业发展的重要组成部分&#xff0c;它以数字化、网络化的方式提供商品和服务。商城系统通过互联网技术&#xff0c;将商品和消费者紧密连接&#xff0c;方便了购物的流程和效率。 商城系统的特点之一是无国界化。传统实体商店通常受限于地理位置和时间&…...

同步_异步请求和Ajax并利用axios框架简化

目录 同步和异步 原生的Ajax 创建XMLHttpRequest对象 常用方法 常用属性 axios框架 同步和异步 同步请求&#xff1a;发送请求后&#xff0c;会做出回应&#xff0c;回应的内容会覆盖浏览器中的内容&#xff0c;这样会打断其他正常的操作&#xff0c;显得不太友好&#…...

取个对象值导致系统崩溃

取个对象值导致系统崩溃 前言 想必各位小伙经常在项目中遇到一些错误&#xff0c;取对象值的时候&#xff0c;经常报错,又或者某些项目突然就挂经常都是出现在一些对象取值上面&#xff0c;然后就被领导一顿训斥 报错分析 例如&#xff1a; 下面这个报错大家想必不会陌生&am…...

nestjs 基础、使用 passport 来进行鉴权

回顾一些定义 NestJS 部分 Module 模块结构 模块是一个图状引用关系。 模块的实例化有三种模式。默认情况是 singletones 模式&#xff0c;也就是模块可能被引用&#xff0c;但不同的引用处拿的是同一个共享实例&#xff0c;也就是说一个进程有一个唯一的实例被共享。 模块&a…...

1.1 : DNA 螺旋

概述 脱氧核糖核酸(DNA)是负责在所有生物体和大多数病毒中代代相传性状的遗传物质。DNA由两条相互缠绕形成双螺旋的核苷酸链组成。DNA 结构的发现是在近一个世纪的时间里逐步发现的,代表了科学史上最著名、最迷人的故事之一。 DNA 结构详细信息 每条 DNA 链均由称为核苷酸…...

.gitignore匹配规则

目录 1.直接一个名称2.斜杠 /3.符号 *4.问号 &#xff1f;5.感叹号 &#xff01;6.gitkeep 借鉴抖音账号&#xff1a; 渡一前端提薪课 1.直接一个名称 会忽略目录下的所有该名称文件和文件夹&#xff0c;无论嵌套多深。 2.斜杠 / 1.斜杠在开头(/dist)&#xff1a;忽略和.gitig…...

Python-OpenCV中的图像处理-GrabCut算法交互式前景提取

Python-OpenCV中的图像处理-GrabCut算法交互式前景提取 Python-OpenCV中的图像处理-GrabCut算法交互式前景提取 Python-OpenCV中的图像处理-GrabCut算法交互式前景提取 cv2.grabCut(img: Mat, mask: typing.Optional[Mat], rect, bgdModel, fgdModel, iterCount, mode…) img…...

JAVA 鼠标控制与键盘输入控制

核心类&#xff1a;java.awt.Robot 该类是JDK定义的电脑系统的抽象类,可以用来模拟实现鼠标点击与键盘输入等信息 简单实现一个自动抢票代码&#xff1a; Robot rt new Robot();//可以认为是操作间隔的停歇时间&#xff0c;比如等待页面加载&#xff0c;等弹框内容展示等 r…...

VB+SQL宿舍管理系统设计与实现

摘要 统是采用Visual Basic作为前台开发工具,SQL Server作为后台数据库平台的基于C/S的两层模式的管理系统。宿舍管理系统是目前各所高校后勤管理之中的重要部分,如何能科学有效的开展好宿舍管理部分的工作,是当前高校领导人和后勤管理人员关心的问题。因此,宿舍管理部分工…...

自律人生:戒断视频、游戏、小说、躺在床上不玩手机、睡觉前总结和冥想(提升注意力、专注度)

以下是一些方法来戒断视频、游戏、小说、躺在床上不玩手机&#xff0c;以及提高注意力和专注力。 制定计划 制定一个详细的计划&#xff0c;包括要戒断的东西、时间表以及对于成功戒断的奖励。这将帮助你保持目标&#xff0c;让你更容易达到成功。 找到替代品 尝试找到其他…...

学习笔记十四:K8S最小调度单元POD概述

K8S最小调度单元POD概述 k8s核心资源Pod介绍Pod是什么Pod如何管理多个容器Pod网络Pod存储代码自动发版更新收集业务日志 Pod工作方式自主式Pod控制器管理的Pod(防误删除) 如何基于Pod运行应用 k8s核心资源Pod介绍 K8s官方文档&#xff1a;https://kubernetes.io/ K8s中文官方文…...

ARM--day2(cpsr、spsr、数据搬移指令、移位操作指令、位运算操作指令、算数运算指令、比较指令、跳转指令)

.text .global _gcd _gcd:mov r0,#9mov r1,#15b loop loop:cmp r0,r1beq stopsubhi r0,r1bhi loopsubcc r1,r0bcc loopstop:b stop.end用for循环实现1~100之间和5050 .text .global _gcd _gcd:mov r0,#0x0mov r1,#0x1mov r2,#0x64b loop loop:cmp r1,r2bhi stopadd r0,r0,r1ad…...

idea报错:java: 程序包org.springframework.web.bind.annotation不存在

这个错误通常都是maven仓库的问题&#xff0c;试了网上很多方法&#xff0c;都没有解决&#xff0c;如果大家有遇到这个问题&#xff0c;且试了很多方法之后都没有解决&#xff0c;不妨可以试试我这个方法 先编译一下已经写好的代码&#xff0c;这时候会出现以上报错&#xff…...

REPENTOGON全面安装指南:深度解锁以撒结合脚本扩展器功能

REPENTOGON全面安装指南&#xff1a;深度解锁以撒结合脚本扩展器功能 【免费下载链接】REPENTOGON Script extender for The Binding of Isaac: Repentance 项目地址: https://gitcode.com/gh_mirrors/re/REPENTOGON 想要为《以撒的结合&#xff1a;悔改》带来革命性的游…...

根据应用场景TongWeb版本选购指南

TongWeb7.0.4企业版TongWeb8.0/7.0.8企业版&#xff08;主推&#xff09;TongWeb7.0.E/8.0.E嵌入版TongHttpServer(THS)应用开发语言JavaEE应用JavaEE/JakartaEE应用JavaEE/JakartaEE应用PHP应用、vue前端应用说明&#xff1a;1. PHP应用直接推荐THS。2. .NET Core应用不需要中…...

开源工具本地化实践:FigmaCN插件让设计协作更高效

开源工具本地化实践&#xff1a;FigmaCN插件让设计协作更高效 【免费下载链接】figmaCN 中文 Figma 插件&#xff0c;设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 在全球化协作与本地化需求日益增长的今天&#xff0c;开源工具本地化已成为…...

OpenClaw技能扩展:安装Qwen3-4B专用插件实现代码生成

OpenClaw技能扩展&#xff1a;安装Qwen3-4B专用插件实现代码生成 1. 为什么需要Qwen3-4B专用技能 作为一个长期与代码打交道的开发者&#xff0c;我一直在寻找能够提升编码效率的工具。当我第一次接触OpenClaw时&#xff0c;最吸引我的不是它的基础自动化能力&#xff0c;而是…...

PlugY:重塑暗黑破坏神2单机体验的技术突破

PlugY&#xff1a;重塑暗黑破坏神2单机体验的技术突破 【免费下载链接】PlugY PlugY, The Survival Kit - Plug-in for Diablo II Lord of Destruction 项目地址: https://gitcode.com/gh_mirrors/pl/PlugY 一、问题篇&#xff1a;暗黑破坏神2单机模式的技术痛点 作为一…...

tao-8k嵌入模型实测:Xinference免配置部署,长文本处理效率翻倍

tao-8k嵌入模型实测&#xff1a;Xinference免配置部署&#xff0c;长文本处理效率翻倍 1. 引言&#xff1a;长文本嵌入的工程挑战 在自然语言处理领域&#xff0c;文本嵌入模型扮演着至关重要的角色。它们将文本转换为高维向量表示&#xff0c;为语义搜索、文档聚类、问答系统…...

【后端】主流后端语言横向对比:JAVA、C、C++、GO、PYTHON的实战应用与选型指南

1. 五种主流后端语言的核心特性对比 第一次接触后端开发时&#xff0c;面对众多编程语言的选择确实容易犯难。我至今记得2013年参与电商系统重构时&#xff0c;团队为选择Java还是Go争论了两周。这五种语言就像不同的工具——没有绝对的好坏&#xff0c;关键要看用在什么场景。…...

Windows 10 PL-2303串口驱动终极修复指南:告别老旧芯片兼容性问题

Windows 10 PL-2303串口驱动终极修复指南&#xff1a;告别老旧芯片兼容性问题 【免费下载链接】pl2303-win10 Windows 10 driver for end-of-life PL-2303 chipsets. 项目地址: https://gitcode.com/gh_mirrors/pl/pl2303-win10 还在为Windows 10系统下PL-2303串口适配器…...

STM32CubeMX实战:串口中断配置与数据收发全解析

1. 从零开始搭建STM32CubeMX工程 第一次接触STM32CubeMX时&#xff0c;我被它强大的可视化配置功能惊艳到了。这个由ST官方推出的工具&#xff0c;简直就是嵌入式开发者的福音。相比传统的手动编写初始化代码&#xff0c;CubeMX通过图形界面就能完成大部分硬件配置&#xff0c;…...

用ESP32和2.13寸电子价签墨水屏,DIY一个超省电的桌面网络时钟(附完整代码)

用ESP32和2.13寸电子价签墨水屏打造极简网络时钟&#xff1a;从硬件拆解到代码实战 在智能设备泛滥的今天&#xff0c;一块能安静显示时间且不打扰生活的时钟反而成了稀罕物。本文将带你用ESP32开发板和汉朔2.13寸电子价签墨水屏&#xff0c;打造一个年耗电量不足1度电的极简网…...