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 的增强和泛化,为交换两个变量(可以是int等内置数据类型,或者是类实例、容器)的值提供了便捷的方法。 为了使用boost::swap,需要包含头文件<boost/swap.hpp>ÿ…...
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,以及异步组件
目录 想实现切换不同列表展示不同数据方法一方法二,动态组件动态组件的父组件如何传的值动态组件的子组件如何接受传的值 认识keep-alive缓存组件的生命周期 异步组件,单独打包,实现webpack分包,如何对组件进行单独打包࿰…...
C++的IO流
目录 C语言的输入与输出 流是什么 CIO流 C标准IO流 C文件IO流 stringstream的简单介绍 在C语言中,如果想要将一个整形变量的数据转化为字符串格式,如何去做? 将数值类型数据格式化为字符串 字符串拼接 序列化和反序列化结构数据 注…...
nodejs+vue+elementui电影订票网站系统_wqc3k
电影订票系统在国内有很多值得借鉴的例子,功能也都趋于完善,因此此次电影订票系统将轻量化开发,要完成以下功能: (1)要支持完整的用户注册,登录功能,账号的管理通过管理员来实现。 &…...
2023-08-14 linux 串口终端输入长命令不换行,覆盖前面内容,stty命令设置串口终端行列数
一、linux 串口终端输入长命令不换行,覆盖前面内容,现象如下图: 二、解决方法:用stty 命令设置行列数 stty columns 200 stty rows 10三、参考文章 https://www.cnblogs.com/goloving/p/15170537.html 常用Linux串口设备操作命…...
根据指定日期获取周,月,季度,年的第一天和最后一天
1. 根据指定日期获取周,月,季度,年的第一天和最后一天 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date;/*** 根据给定时间获取周、月度、季度、年度开始结束时间*…...
CRMEB商城系统:便捷、安全、多样化的购物方式
商城系统是当今社会商业发展的重要组成部分,它以数字化、网络化的方式提供商品和服务。商城系统通过互联网技术,将商品和消费者紧密连接,方便了购物的流程和效率。 商城系统的特点之一是无国界化。传统实体商店通常受限于地理位置和时间&…...
同步_异步请求和Ajax并利用axios框架简化
目录 同步和异步 原生的Ajax 创建XMLHttpRequest对象 常用方法 常用属性 axios框架 同步和异步 同步请求:发送请求后,会做出回应,回应的内容会覆盖浏览器中的内容,这样会打断其他正常的操作,显得不太友好&#…...
取个对象值导致系统崩溃
取个对象值导致系统崩溃 前言 想必各位小伙经常在项目中遇到一些错误,取对象值的时候,经常报错,又或者某些项目突然就挂经常都是出现在一些对象取值上面,然后就被领导一顿训斥 报错分析 例如: 下面这个报错大家想必不会陌生&am…...
nestjs 基础、使用 passport 来进行鉴权
回顾一些定义 NestJS 部分 Module 模块结构 模块是一个图状引用关系。 模块的实例化有三种模式。默认情况是 singletones 模式,也就是模块可能被引用,但不同的引用处拿的是同一个共享实例,也就是说一个进程有一个唯一的实例被共享。 模块&a…...
1.1 : DNA 螺旋
概述 脱氧核糖核酸(DNA)是负责在所有生物体和大多数病毒中代代相传性状的遗传物质。DNA由两条相互缠绕形成双螺旋的核苷酸链组成。DNA 结构的发现是在近一个世纪的时间里逐步发现的,代表了科学史上最著名、最迷人的故事之一。 DNA 结构详细信息 每条 DNA 链均由称为核苷酸…...
.gitignore匹配规则
目录 1.直接一个名称2.斜杠 /3.符号 *4.问号 ?5.感叹号 !6.gitkeep 借鉴抖音账号: 渡一前端提薪课 1.直接一个名称 会忽略目录下的所有该名称文件和文件夹,无论嵌套多深。 2.斜杠 / 1.斜杠在开头(/dist):忽略和.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 鼠标控制与键盘输入控制
核心类:java.awt.Robot 该类是JDK定义的电脑系统的抽象类,可以用来模拟实现鼠标点击与键盘输入等信息 简单实现一个自动抢票代码: Robot rt new Robot();//可以认为是操作间隔的停歇时间,比如等待页面加载,等弹框内容展示等 r…...
VB+SQL宿舍管理系统设计与实现
摘要 统是采用Visual Basic作为前台开发工具,SQL Server作为后台数据库平台的基于C/S的两层模式的管理系统。宿舍管理系统是目前各所高校后勤管理之中的重要部分,如何能科学有效的开展好宿舍管理部分的工作,是当前高校领导人和后勤管理人员关心的问题。因此,宿舍管理部分工…...
自律人生:戒断视频、游戏、小说、躺在床上不玩手机、睡觉前总结和冥想(提升注意力、专注度)
以下是一些方法来戒断视频、游戏、小说、躺在床上不玩手机,以及提高注意力和专注力。 制定计划 制定一个详细的计划,包括要戒断的东西、时间表以及对于成功戒断的奖励。这将帮助你保持目标,让你更容易达到成功。 找到替代品 尝试找到其他…...
学习笔记十四:K8S最小调度单元POD概述
K8S最小调度单元POD概述 k8s核心资源Pod介绍Pod是什么Pod如何管理多个容器Pod网络Pod存储代码自动发版更新收集业务日志 Pod工作方式自主式Pod控制器管理的Pod(防误删除) 如何基于Pod运行应用 k8s核心资源Pod介绍 K8s官方文档: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仓库的问题,试了网上很多方法,都没有解决,如果大家有遇到这个问题,且试了很多方法之后都没有解决,不妨可以试试我这个方法 先编译一下已经写好的代码,这时候会出现以上报错ÿ…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
