编程参考 - std::exchange和std::swap的区别

这两个功能是C++ standard library中的Standard template library中的一部分。容易混淆,我们来看下它们的区别。

exchange:

这个函数是一个返回原先值的set函数。

std::exchange is a setter returning the old value. 

int z = std::exchange(x, y);

After this line of code executes:

* x is assigned the value of y,

* z is assigned the value that x had initially.

使用伪代码(pseudocode)表示的话,exchange的意思就是:

z <- x <- y

x(第一个参数)的值作为返回值赋值给z;y(第二个参数)的值复制给X。

常用语法定义如下:

template< class T, class U = T >

T exchange( T& obj, U&& new_value );

将第二个参数的值赋给第一个值,并返回第一个参数的旧值。

#include <utility>

int main()

{

  int x = 2;

  auto y = std::exchange(x, 4);

  // y == 2;

  // x == 4;

}

swap:

伪代码表示含义:

A -> B

B <- A

交换两个变量的值。

Semantic and syntax,语义和语法:

最通常的使用语法如下:

template< class T >

void swap( T& a, T& b );

对模板T类型的要求:

T must meet the requirements of CopyConstructible and CopyAssignable (until C++11),MoveConstructible and MoveAssignable (since C++11)

注意swap是不返回值的。这里的参数是对象的引用。

#include <utility>

int main()

{

  int i = 3;

  int j = 4;

  std::swap(i, j);

  // i == 4

  // j == 3

}

$ g++ -o test std.c -std=c++14

swap需要他的参数都不是常量引用,要能转换为一个non-const reference,所以不能使用swap(i, 4),编译会不通过。

使用exchange的场景举例:The “swap-and-iterate” pattern 

这种模式可以使用exchange来做。在很多event-driven的架构中会使用。一般会有一个vector的事件需要分发(dispatch), 或者等同的意思,需要调用相应的callback。 但我们希望事件处理程序能够产生自己的事件,以便进行延迟分派。(But we want event handlers to be able to produce events of their own for deferred dispatch.)

代码如下:

class Dispatcher {

    // We hold some vector of callables that represents

    // events to dispatch or actions to take

    using Callback = /* some callable */;

    std::vector<Callback> callbacks_;

    // Anyone can register an event to be dispatched later

    void defer_event(const Callback& cb) {

        callbacks_.push_back(cb);

    }

    // All events are dispatched when we call process

    void process() {

        std::vector<Callback> tmp{};

        using std::swap; // the "std::swap" two-step

        swap(tmp, callbacks_);

        for (const auto& callback : tmp) {

            std::invoke(callback);

        }

    }

};

这就是 "swap-and-iterate "模式。这个回调类内部调用 defer_event 并因此产生自己的事件是安全的:我们使用 tmp,这样调用 defer_event 就不会使循环中的迭代器失效。

但是,我们在这里做的工作比必要的要多一些,而且还犯了 "ITM antipattern(initialize-then-modify)"的错误。首先,我们构造了一个空vector (tmp),然后,通过 swap,我们有 3 个move assignments,然后才开始迭代。

使用std::exchange进行重构可以解决这些问题:

class Dispatcher {

    // ...

    // All events are dispatched when we call process

    void process() {

        for (const auto& callback : std::exchange(callbacks_, {}) {

            std::invoke(callback);

        }

    }

};

现在,我们不必再声明一个临时量。在 std::exchange 中,我们只有一个移动构造和一个移动赋值,比 swap 节省了一次移动。我们不需要理解 "std::swap 两步法"所涉及的 ADL。我们不需要 tmp,只需要一种表达empty vector的方法,在这里就是 {}。编译器非常善于优化对 std::exchange 的调用,所以我们当然能得到我们通常期望的拷贝消除(copy elision)。因此,代码整体上更加简洁、快速(concise, faster),并提供了与之前相同的安全性。

从这个角度看exchange就是用来调整一个变量的值来使用的。就像我们一直在用的i++, 后缀操作符,在使用完i的值后,再对i的值进行修改。

参考:

1,C++ Weekly: Ask C++ Weekly: `std::exchange` vs `std::swap`

https://youtu.be/GEbPRS81py4?si=9tvUhpGjKstzCog7

2,cppreference.com

std::exchange - cppreference.com

std::swap - cppreference.com

3,std::exchange是干什么的

What std::exchange does, and how to remember it - Fluent C++ (fluentcpp.com)

4,std::exhange的好处

std::exchange Patterns: Fast, Safe, Expressive, and Probably Underused - Fluent C++ (fluentcpp.com)

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

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

相关文章

C语言指针详解(3)———指针题目,你确定你学会指针了?进来看看吧!(几十个指针小题+超详解)

你确定你学会指针了&#xff1f; 你确定你明白数组名了&#xff1f; 如果你觉得你学的还不错&#xff0c;就进来看看吧&#xff0c;相信你看完之后一定能收获更多。 数组名的理解一定要弄清楚 数组名是数组首元素的地址 但是有2个例外&#xff1a; sizeof(数组名)&#xff0c;这…

【MySQL多表查询以及事务、索引】

1. 多表查询 1.1 概述 1.1.1 数据准备 #建议&#xff1a;创建新的数据库 create database db04; use db04;-- 部门表 create table tb_dept (id int unsigned primary key auto_increment comment 主键ID,name varchar(10) not null unique comment 部门名称…

Jmeter 实现 mqtt 协议压力测试

1. 下载jmeter&#xff0c;解压 https://jmeter.apache.org/download_jmeter.cgi 以 5.4.3 为例&#xff0c;下载地址&#xff1a; https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.4.3.zip linux下解压&#xff1a; unzip apache-jmeter-5.4.3.zip 2. 下载m…

proxy相对于object.defineproperty有哪些优点?

Proxy相对于Object.defineProperty的优点有1&#xff1a; 功能更强大&#xff1a;Proxy提供了更灵活的方式来操作对象&#xff0c;可以捕获和定制对象的各种操作&#xff0c;包括获取属性、设置属性、删除属性等。捕获多种操作&#xff1a;Proxy可以捕获多种不同的操作&#x…

在线海报图片设计器、图片编辑器源码/仿照稿定设计源码

在线海报设计系统素材设计源码是一个漂亮且功能强大的在线海报图片设计器&#xff0c;仿照稿定设计而成。该系统适用于多种场景&#xff0c;包括海报图片生成、电商分享图、文章长图、视频/公众号封面等。用户无需下载软件&#xff0c;即可轻松实现创意&#xff0c;迅速完成排版…

使用 React Native 针对 Android 进行开发

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 概述 通过安装所需工具开始使用 React Native 创建新的 React Native 项目 本指南将有助于开始使用 Windows 上的…

性能测试工具有哪些?原理是什么?怎么选择适合的工具?

前言 本篇文章主要简单总结下性能测试工具的原理以及如何选型。性能测试和功能测试不同&#xff0c;性能测试的执行是基本功能的重复和并发&#xff0c;需要模拟多用户&#xff0c;在性能测试执行时需要监控指标参数&#xff0c;同时性能测试的结果不是那么显而易见&#xff0…

43.228.64.X游戏盾在业务高峰时间段,出现用户大量掉线问题,可能是什么原因导致

服务器负载过高&#xff1a;业务高峰期间&#xff0c;服务器可能无法处理大量的用户请求&#xff0c;导致性能下降&#xff0c;甚至引起服务器崩溃&#xff0c;从而导致用户掉线。 网络带宽不足&#xff1a;当大量用户同时访问游戏盾时&#xff0c;网络带宽可能不足以支持所有…

Smart Community(1)之设计规范

通过前面大数据开发相关知识的学习&#xff0c;准备做一个项目进行练习---我给他起了一个响亮的名字&#xff1a;基于HadoopHA的智慧社区服务平台 设计规范&#xff1a; 做一个项目之前肯定要先规定一些开发过程中的设计规范 &#xff08;一&#xff09;数据埋点规范&#xf…

linux jenkins2.414.1-1.1版本安装

文章目录 前言一、rpm文件下载二、安装jenkins2.1.升级jdk1.82.2安装jenkins2.3 启动服务2.4 使用密码登录2.5 修改插件源2.6 汉化插件安装演示 总结 前言 之前也安装过jenkins&#xff0c;但是那个版本是2.1的&#xff0c;太老了很多插件都不支持&#xff0c;现在安装目前为止…

XSS笔记

一、xss漏洞通常是通过php的输出函数将javascript代码输出到html页面中&#xff0c;通过用户本地浏览器执行的&#xff0c;所以xss漏洞关键就是寻找参数未过滤的输出函数。 二、XSS的攻击方式 1、 反射型XSS&#xff1a;<非持久化> 攻击者事先制作好攻击链接, 需要欺骗用…

RocketMq(一)安装部署

一、linux单机部署&#xff1a; 1、到apache官网下载 | RocketMQ (apache.org)下载binary zip包&#xff0c;如我下载的4.9.6版本。 上传到建好的/usr/local/rocketmq目录下。 2、解压zip包 unzip rocketmq-all-4.9.6-bin-release.zip 3、进入解压后的文件夹,启动 Name Serv…

vue之$emit返回值

使用场景&#xff1a;子组件调用父组件的方法并获取到父组件方法的返回值 方法(一): 回调函数: 1.子组件方法&#xff1a; ……methods:{ShowMore(step){this.$emit("ChildClick",step,(res)>{//回调函数的方法体.处理自己的业务.});}}…… 2、父组件方法 ……

java23种设计模式与追MM

1、FACTORY—追MM少不了请吃饭了&#xff0c;麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西&#xff0c;虽然口味有所不同&#xff0c;但不管你带MM去麦当劳或肯德基&#xff0c;只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory 工厂模式&#xff1a…

02目标检测-传统检测方法

目录 一、目标学习的检测方法变迁及对比 二、 基于传统手工特征的检测算法的定义 三、传统主要手工特征与算法 Haar特征与 人脸检测算法 - Viola-Jones(了解) HOG特征与 SVM 算法(了解)&#xff08;行人检测、opencv实现&#xff09; SIFT特征与SIFT算法(了解) DPM&#…

redis--windows配置--redis基础

写在前面&#xff1a; 文章目录 win安装配置密码配置服务服务已经存在 可视化工具运行类型基础类型 帮助文档命令通用命令string命令hashlistsetsortedset win安装 下载地址 然后一路next就可以了。 记得添加到环境变量 配置密码 在目录打开配置文件 搜索requirepass …

Fluent实现大量气泡的随机分布案例

1、问题介绍 气液两相管流在石油、化工、能源、制冷等工业领域中大量存在。气泡在生存发展过程中往往会导致噪声和引起管道振动&#xff0c;自来水管路中如有空气时往往会产生啸叫声和管道剧烈振动。掌握流动过程中气泡的生成、发展及其破裂等动力规律是控制气液两相流气动噪声…

C++qt day8

1.用代码实现简单的图形化界面&#xff08;并将工程文件注释&#xff09; 头文件 #ifndef MYWIDGET_H #define MYWIDGET_H //防止头文件冲突#include <QWidget> //父类的头文件class MyWidget : public QWidget //自定义自己的界面类&#xff0c;公共继承…

【pygame】01 pygame制作游戏的最小系统

这次使用sublimepython进行pygame的游戏开发&#xff0c;目的是学习使用python的基本操作和常用模块 添加一个文件夹到工程 最小系统 1.导入使用的模块 2.初始化&#xff1a;pygame.init函数包含了各个子模块的初始化&#xff0c;可以重复调用 3.pygame.display.set_mode返…

<OpenCV> Mat属性

OpenCV的图像数据类型可参考之前的博客&#xff1a;https://blog.csdn.net/thisiszdy/article/details/120238017 OpenCV-Mat类型的部分属性如下&#xff1a; size&#xff1a;矩阵的大小&#xff0c; s i z e ( c o l s , r o w s ) size(cols,rows) size(cols,rows)&#xf…