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

[C++面试] 对通透比较器了解多少?(较少涉及,可跳过)

一、入门

1、什么是比较器

在 C++ 中,比较器是一个可调用对象(函数、函数对象或 Lambda 表达式),用于定义元素之间的比较规则。

用途:通常作为参数传递给标准库中的排序函数或关联容器,以指定元素的顺序。

    std::vector<int> numbers = {5, 2, 8, 1, 9};// 使用 Lambda 表达式作为比较器进行降序排序std::sort(numbers.begin(), numbers.end(), [](int a, int b) {return a > b;});

Lambda 表达式 [](int a, int b) { return a > b; } 作为比较器传递给 std::sort 函数,用于定义降序排序规则。 

2、什么是通透比较器(Transparent Comparator)

通透比较器是一种允许模板参数自动推导类型的比较器

解决泛型编程中比较器与容器元素类型严格绑定的问题(例如std::set默认要求比较器类型与元素类型一致)

通过使用std::less<>(C++17起默认支持通透性),可以直接比较不同类型的数据(如字符串和字符串视图),无需显式类型转换

std::set<std::string, std::less<>> s; // 使用通透比较器
s.find("hello"); // 可直接传入const char*类型,无需构造std::string

二、进阶

1、如何使用自定义的函数对象作为比较器来对自定义类型的对象进行排序?

// 定义自定义比较器函数对象
class AgeComparator {
public:bool operator()(const Person& p1, const Person& p2) const {return p1.age < p2.age;}
};

使用如下:

class Person {
public:std::string name;int age;Person(const std::string& n, int a) : name(n), age(a) {}
};int main() {std::vector<Person> people = {{"Alice", 25},{"Bob", 20},{"Charlie", 30}};// 使用自定义比较器进行排序std::sort(people.begin(), people.end(), AgeComparator());return 0;
}

2、通透比较器与传统比较函数有何区别?

  • 传统比较器:需显式指定元素类型(如std::less<std::string>),要求参数类型严格匹配,否则需要类型转换。
  • 通透比较器:通过类型透传(operator()(const auto& a, const auto& b))允许模板自动推导类型,支持异构比较。例如std::less<>可以比较std::stringconst char*

3、为什么通透比较器需要严格弱序保证?违反时可能引发哪些问题? 

  • 严格弱序要求:传递性(若a < bb < c,则a < c)、反对称性(a < bb < a不能同时成立)等。
  • 问题示例:若比较器未满足严格弱序,std::set等容器可能出现元素重复或查找失败(未定义行为)

三、高阶

1、如何实现一个自定义通透比较器?核心机制是什么?

类型透传:通过模板参数推导(如operator()的参数为通用引用)

严格弱序:确保比较逻辑满足严格弱序规则(传递性、反对称性等)

struct LengthCompare {template <typename T, typename U>bool operator()(T&& a, U&& b) const {return a.size() < b.size(); // 支持任意有size()成员的类型}
};
std::set<std::string, LengthCompare> s; // 按长度排序

2、​C++20的三向比较运算符(<=>)与通透比较器的关系是什么?

<=>(太空船运算符)简化了比较逻辑的定义,通过返回std::strong_ordering等类型自动生成全部比较运算符(如<==

通透比较器可与<=>结合,例如在自定义比较器中直接调用a <=> b实现类型透明的比较逻辑:

struct TransparentCompare {template <typename T, typename U>auto operator()(T&& a, U&& b) const -> decltype(a <=> b) {return a <=> b; // 自动推导比较结果类型}
};

 3、​通透比较器在模板元编程中的优化意义是什么?举例说明SFINAE如何支持通透性。

优化意义:避免模板特化冗余,通过单一模板适配多种类型。例如std::map使用通透比较器时,find()可接受任意可比较类型,减少运行时构造临时对象的开销。

SFINAE(Substitution Failure Is Not An Error)替换失败并非错误,是 C++ 模板元编程的核心技术,允许编译器在模板参数替换失败时忽略该候选函数/类,而非直接报错。其核心思想是:​通过编译期的条件筛选,选择最合适的模板实现

template <typename T>
struct Compare {template <typename U>auto operator()(const T& a, const U& b) const -> decltype(a < b, std::true_type{}) { // 仅当a < b合法时启用return a < b;}
};

4、设计一个支持异构查找的容器,要求使用通透比较器和C++20特性

std::strong_ordering 是 C++20 引入的三向比较运算符(<=>,飞船运算符)的返回类型之一,用于表示两个对象之间的严格顺序关系。它属于强序(Strong Ordering),要求比较结果满足以下特性:

  • 传递性:若 a < b 且 b < c,则 a < c
  • 反对称性:若 a < b,则 b > a
  • 完全性:任意两个值必须可比较(不存在无法比较的情况)

此外还有:std::weak_ordering、std::partial_ordering

#include <set>
#include <string>
#include <compare>struct HeterogeneousCompare {template <typename T, typename U>auto operator()(T&& a, U&& b) const -> std::strong_ordering {return a <=> b; // 使用三向比较运算符}
};std::set<std::string, HeterogeneousCompare> s;
s.emplace("apple");
bool exists = s.contains("apple"); // 直接传入字符串字面量

相关文章:

[C++面试] 对通透比较器了解多少?(较少涉及,可跳过)

一、入门 1、什么是比较器 在 C 中&#xff0c;比较器是一个可调用对象&#xff08;函数、函数对象或 Lambda 表达式&#xff09;&#xff0c;用于定义元素之间的比较规则。 用途&#xff1a;通常作为参数传递给标准库中的排序函数或关联容器&#xff0c;以指定元素的顺序。…...

nslookup的使用

nslookup 是一个网络管理命令行工具&#xff0c;用于查询域名系统 (DNS) 服务器来获取有关主机名和IP地址的信息。它可以帮助你检查DNS记录、解析域名到IP地址或者执行反向查找&#xff08;从IP地址找到对应的域名&#xff09;。下面是 nslookup 的一些基本用法&#xff1a; 基…...

ES5 vs ES6:JavaScript 演进之路

ES5 vs ES6&#xff1a;JavaScript 演进之路 JavaScript版本演进ES5 (ECMAScript 5)ES6 (ECMAScript 2015)版本演进时间线为什么ES6如此重要&#xff1f; ES5 vs ES61. 变量声明对比2. 函数特性对比3. 类和对象4. 模块化5. 解构和展开6. 字符串和模板字面量7. 数组和对象新方法…...

函数式编程的核心

函数式编程 函数式编程&#xff08;funcitonal programming&#xff09;其实是个很古老的概念。 高阶函数和内存分析 函数式一阶公民 函数式编程最鲜明的特点就是&#xff1a;函数式一等公民&#xff0c;指的是函数与其他数据类型一样&#xff0c;处于平等地位&#xff0c;可…...

【易康eCognition实验教程】006:在影像上添加文本

在某些情况下&#xff0c;希望能在影像上面显示文本文字&#xff0c;例如&#xff0c;一个地图的名称或者是多时相影像分析的年或月的显示。此外&#xff0c;文本如果作为一个规则集导出的部分则可以被纳入数字影像中。如下图所示&#xff1a; 若要添加文本&#xff0c;在影像视…...

Django ORM自定义排序的实用示例

在使用Django进行开发时&#xff0c;ORM&#xff08;对象关系映射&#xff09;是一个非常强大的工具。它让我们可以用Python代码直接操作数据库&#xff0c;而不需要写SQL语句。当我们需要对数据进行排序时&#xff0c;Django ORM同样提供了丰富的功能。今天&#xff0c;我们就…...

【后端】【ubuntu】 ubuntu目录权限查看的几种方法

在Ubuntu中&#xff0c;有多种方式可以查看目录或文件的权限&#xff0c;以下为你详细介绍常见的指令及其使用方法&#xff1a; 1. ls -l 命令 这是最常用的查看文件和目录权限的命令&#xff0c;-l 选项用于以长格式列出文件和目录的详细信息&#xff0c;其中就包含权限信息…...

C++【类和对象】(超详细!!!)

C【类和对象】 1.运算符重载2.赋值运算符重载3.日期类的实现 1.运算符重载 (1).C规定类类型运算符使用时&#xff0c;必须转换成调用运算符重载。 (2).运算符重载是具有特殊名字的函数&#xff0c;名字等于operator加需要使用的运算符&#xff0c;具有返回类型和参数列表及函数…...

如何简单预估大模型运行所需的显存

模型消耗的显存主要来源于模型参数&#xff0c;前向/反向&#xff0c;梯度以及优化器…… 1、为什么显存很重要 显存就是显卡的“仓库”和“高速公路”。 容量越大&#xff0c;能存储的图形数据就越多&#xff0c;就能支持更高分辨率、更高纹理质量的游戏或图形程序。 速度越…...

Excel 中如何实现数据透视表?

Excel 中如何实现数据透视表&#xff1f; 数据透视表&#xff08;PivotTable&#xff09;是 Excel 中强大的数据分析工具&#xff0c;能够快速汇总、分析和展示大量数据。本文将详细介绍如何在 Excel 中创建和使用数据透视表。 1. 数据透视表的基本概念 数据透视表是一种交互…...

C语言中getchar和putchar函数详解,理解多组数据输入的问题中的EOF(-1)

引言 C语言中getchar和putchar函数详解&#xff0c;理解多组数据输入的问题中的EOF&#xff08;-1&#xff09;。 1.getchar() 函数原型&#xff1a; int getchar ( void ); getchar() 函数返回用户从键盘输入的一个字符&#xff0c;使用时不带有任何参数。 程序运行到这个命…...

python基础知识补充

一.区分列表、元组、集合、字典&#xff1a; 二.输出&#xff1a; <1>格式化输出字符串&#xff1a; 格式符号转换%s字符串%d有符号的十进制整数%f浮点数%c字符%u无符号十进制整数%o八进制整数%x十六进制整数&#xff08;小写ox&#xff09;%X十六进制整数(大写OX)%e科…...

MySql自动安装脚本

一、脚本安装流程 1. 添加MySQL的Repository 使用wget命令从MySQL官方网站下载Yum Repository的RPM包。使用rpm -ivh命令安装下载的RPM包&#xff0c;以添加MySQL的Yum Repository。 2. 安装mysql-community-server 使用yum install -y mysql-community-server --nogpgchec…...

STM32-I2C通信外设

目录 一&#xff1a;I2C外设简介 二&#xff1a;I2C外设数据收发 三&#xff1a;I2C的复用端口 四&#xff1a;主机发送和接收 五&#xff1a;硬件I2C读写MPU6050 相关函数&#xff1a; 1.I2C_ GenerateSTART 2.I2C_ GenerateSTOP 3.I2C_ AcknowledgeConfig 4.I2C…...

【脚本】Linux一键扩大虚拟内存的大小

Linux增加虚拟内存其实很简单 就那几个命令&#xff0c;free、mkswap、swapon 但是方便起见我写成了脚本 使用方法 进入你的目录&#xff0c; nano ./install_swap.sh 下面的脚本全文复制&#xff0c;粘贴进去之后&#xff0c;按ctrlx后按y保存 然后运行以下命令 sudo bash …...

信号隔离器 0-20mA/0-10V模拟信号隔离模块变送器 一进二出高精度

信号隔离器 0-20mA/0-10V模拟信号隔离模块变送器 一进二出高精度https://item.taobao.com/item.htm?ftt&id766022047828 型号 一进二出 0-20mA 转0-20mA/0-10V MS-C12 一进二出 0-10V 转 0-20mA/0-10V MS-V12 信号隔离器 单组输出 MS-C1/V1 双组输出 MS-C12/V12 用于…...

Nat. Methods | scPerturb——单细胞扰动数据的标准化资源与统计分析方法

《Nature Methods》提出scPerturb资源平台&#xff0c;整合44个单细胞扰动数据集&#xff08;涵盖转录组、表观组、蛋白组读值&#xff09;&#xff0c;并通过能量统计量&#xff08;E-statistics&#xff09;量化扰动效应&#xff0c;旨在解决单细胞扰动数据的互操作性差、缺乏…...

【易康eCognition实验教程】005:影像波段组合显示与单波段显示

文章目录 一、加载多波段影像二、单波段显示三、彩色显示一、加载多波段影像 二、单波段显示 如果导入的影像数据具有三个或者更多的波段,影像场景将自动以RGB(红绿蓝)模式默认显示,如上图所示。在视图设置(View Settings)窗口中使用单波段灰度显示(Single LayuerGrays…...

使用Process Explorer、Dependency Walker和PE信息查看工具快速排查dll动态库因库与库版本不一致导致的加载失败问题

目录 1、问题说明 2、使用Process Explorer查看目标dll动态库有没有动态加载起来 3、使用Dependency Walker查看xxpadll.dll库的库依赖关系&#xff0c;找到xxpadll.dll加载失败的原因 4、使用PE信息查看工具查看目标dll库的时间戳 5、关于xxsipstack2.dll中调用xxdatanet…...

Git的命令学习——适用小白版

浅要了解一下Git是什么&#xff1a; Git是目前世界上最先进的的分布式控制系统。Git 和其他版本控制系统的主要差别在于&#xff0c;Git 只关心文件数据的整体是否发生变化&#xff0c;而大多数其他系统则只关心文件内容的具体差异。Git 并不保存这些前后变化的差异数据。实际上…...

如何安全处置旧设备?

每年&#xff0c;数百万台旧设备因老化、故障或被新产品取代而被丢弃&#xff0c;这些设备上存储的数据可能带来安全风险。 如果设备没有被正确删除数据&#xff0c;这些数据往往仍可被恢复。因此&#xff0c;安全处置旧设备至关重要。 旧设备可能包含的敏感数据 旧设备中可能…...

Java 学习记录:基础到进阶之路(一)

今天&#xff0c;让我们深入到 Java 项目构建、基础语法及核心编程概念的领域&#xff0c;一探究竟。 软件安装及环境配置请查看之前更新的博客有着详细的介绍&#xff1a; IDEA软件安装&环境配置&中文插件-CSDN博客 目录 1.Java 项目构建基础 1.项目中的 SRC 目录…...

3.3-3.9 蓝桥杯备赛周记

斜率关系 14届省赛 ![[Pasted image 20250205145241.png]] NE555频率解算温度 频率范围外 无效 unsigned int Freq; if(Freq<200) {humnity0;} else if(Freq>2000) {humnity0;} else{ humnity80.0/1800.0 *(float)(Freq-200)10.0;} 斜率计算题 需要类型转换 和数据需要…...

系统架构设计师—系统架构设计篇—软件架构风格

文章目录 概述经典体系结构风格数据流风格批处理管道过滤器对比 调用/返回风格主程序/子程序面向对象架构风格层次架构风格 独立构件风格进程通信事件驱动的系统 虚拟机风格解释器基于规则的系统 仓库风格&#xff08;数据共享风格&#xff09;数据库系统黑板系统超文本系统 闭…...

工厂模式加策略模式 -- 具体实现

这里写目录标题 定义接口定义抽象类定义主处理器分支处理器定义工厂demo 定义接口 public interface EntityHandler extends InitializingBean {MatchContentDTO match(MatchEntityDTO matchEntityDTO);String supportEntityType(); }定义抽象类 public abstract class Abstr…...

STM32---FreeRTOS消息队列

一、简介 1、队列简介&#xff1a; 队列&#xff1a;是任务到任务&#xff0c;任务到中断、中断到任务数据交流的一种机制&#xff08;消息传递&#xff09;。 FreeRTOS基于队列&#xff0c;实现了多种功能&#xff0c;其中包括队列集、互斥信号量、计数型信号量、二值信号量…...

python-leetcode-删掉一个元素以后全为 1 的最长子数组

1493. 删掉一个元素以后全为 1 的最长子数组 - 力扣(LeetCode) 可以使用滑动窗口的方式来解决这个问题。我们要找到最长的全 1 子数组,但必须删除一个元素,因此可以将问题转化为寻找最多包含一个 0 的最长子数组。 解题思路 使用双指针(滑动窗口),维护窗口内最多包含一…...

【赵渝强老师】PostgreSQL的模板数据库

在PostgreSQL中&#xff0c;创建数据库时实际上通过拷贝一个已有数据库进行工作的。在默认情况下&#xff0c;将拷贝名为template1的标准系统数据库。所以该数据库是创建新数据库的“模板”。如果为template1数据库增加对象&#xff0c;这些对象将被拷贝到后续创建的用户数据库…...

vue2中,在table单元格上右键,对行、列的增删操作(模拟wps里的表格交互)

HTML <template><div><divclass"editable-area"v-html"htmlContent"contenteditableblur"handleBlur"contextmenu.prevent"showContextMenu"></div><button click"transformToMd">点击转成M…...

使用DeepSeek+蓝耘快速设计网页简易版《我的世界》小游戏

前言&#xff1a;如今&#xff0c;借助先进的人工智能模型与便捷的云平台&#xff0c;即便是新手开发者&#xff0c;也能开启创意游戏的设计之旅。DeepSeek 作为前沿的人工智能模型&#xff0c;具备强大的功能与潜力&#xff0c;而蓝耘智算云平台则为其提供了稳定高效的运行环境…...