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

C++: Initialization and References to const 初始化和常引用

cpp primer 5e, P97.

理解

这是一段很容易被忽略、 但是又非常重要的内容。

In § 2.3.1 (p. 51) we noted that there are two exceptions to the rule that the type of a reference must match the type of the object to which it refers. The first exception is that we can initialize a reference to const from any expression that can be converted (§ 2.1.2, p. 35) to the type of the reference. In particular, we can bind a reference to const to a nonconst object, a literal, or a more general expression:

对于 reference 来说,只能是如下的其中之一:

  • type of a reference must match the type of the object to which it refers. 引用类型,必须和被引用的类型一样
  • the first exception is that, we can initialize a reference to const from any expression that can be converted to the type of reference
    第一个例外: 如果一个表达式能够转为被引用的类型, 那么这个表达式能被用于初始化一个引用
  • 第二个例外,这里暂时没提及, 应该是右值引用

也就是:
情况1:

T a;
const T& b = a;

情况2:

const T& c = <expression>; // <expression> is type of T, or can be converted to type of T

其中情况2,当表达式不是类型T、但是可以转换为类型T,我想到这几种常见的:

// double/float -> int
const int& r4 = 3.14;// const char* -> std::string
const std::string& s2 = "hello";// non-void pointer -> void*
int* data = (int*) malloc(sizeof(int) * 100);
const void* buf = data;// lambda -> std::function
const std::function<void(int)>& f2 = [](int m) -> void {std::cout << "m is " << m << std::endl;
};
f2(233);// functor -> std::function
struct Wangchuqin
{void operator()(int k){if (k % 3 == 0)std::cout << "遮球" << std::endl;elsestd::cout << "小幅遮球" << std::endl;}
};
Wangchuqin wcq;
const std::function<void(int)>& f3 = wcq;
f3(2025);

实践

// P97#include <iostream>
#include <string>
#include <functional>void echo(int n)
{std::cout << "n is " << n << std::endl;
}struct Wangchuqin
{void operator()(int k){if (k % 3 == 0)std::cout << "遮球" << std::endl;elsestd::cout << "小幅遮球" << std::endl;}
};int main()
{// const reference to intint i = 42;const int& r1 = i; // we can bind a const int& to a plain int objectconst int& r2 = 42; // 42 is an expression, whose type is intconst int& r3 = r1 * 2; // r1 * 2 is an expression, whose type is intconst int& r4 = 3.14;const int& r5 = sizeof(int);// const reference to stringconst std::string s1 = "hello";const std::string& s2 = "hello";// const reference to std::functionconst std::function<void(int)> f1 = echo;f1(42);// labmda -> std::functionconst std::function<void(int)>& f2 = [](int m) -> void {std::cout << "m is " << m << std::endl;};f2(233);// functor -> std::functionWangchuqin wcq;const std::function<void(int)>& f3 = wcq;f3(2025);// const reference to pointerconst void* ptr1 = 0;const void* ptr2 = &i;int* data = (int*) malloc(sizeof(int) * 100);const void* buf = data;free(data);return 0;
}

更实际的实践

https://godbolt.org/z/bcrhc77TM

#include <functional>
#include <vector>
#include <algorithm>
#include <iostream>int main() { using MyFunc = std::function<void(int)>;std::vector<const MyFunc *> myFuncs;auto f = [](int v) {std::cout << v << "\n";};auto pushBack = [&myFuncs](const MyFunc & func) {myFuncs.emplace_back(&func);};pushBack(f);auto callIt  = [val = 1] (const MyFunc* func) {func->operator()(val);};for (auto func : myFuncs) {callIt(func);}
}

上述代码会 crash。 如果开启 ASAN 则能发现非法内存访问。为什么呢?
因为 pushBack(f) 这句不简单呢:

  • f 是 lambda
  • fconst MyFunc & func 发生了转换

这个转换,是生成「临时的」 MyFuncs 对象。这个所谓的「临时的」,可以认为是匿名的、编译器生成的。 这样的匿名对象,声明周期是有限的:发生在 pushBack 定义中,参数传递阶段:

auto pushBack = [&myFuncs](const MyFunc & func) { // 这里

而具体的实现中,压入的是临时对象的地址:

myFuncs.emplace_back(&func);

为啥说是临时对象的地址? 因为 引用的本质是 别名(alias); 取引用的地址, 其实,就是取匿名对象的地址。

匿名对象马上就「死了」,你还取地址; 那以后再用这个匿名对象,就是使用「鬼魂」,本质是使用非法内存。 那肯定crash啊。

当然,如果你还是不信,可以让编译器告诉你, lambda 和 std::function 类型是不一样的:

https://godbolt.org/z/PWcPvzYG1

template<typename T>
void show_type() {
#ifdef __GNUC__std::cout << __PRETTY_FUNCTION__ << "\n";
#elif _MSC_VERstd::cout << __FUNCSIG__ << "\n";
#endif
}show_type<decltype(f)>();
show_type<MyFunc>();
➜  defense-in-cpp git:(main)cd 99 git:(main) ✗ g++ bar.cpp -std=c++11
./%                                                                                                                                                            
➜  9 git:(main) ✗ ./a.out 
void show_type() [T = (lambda at bar.cpp:21:14)]
void show_type() [T = std::function<void (int)>]

相关文章:

C++: Initialization and References to const 初始化和常引用

cpp primer 5e, P97. 理解 这是一段很容易被忽略、 但是又非常重要的内容。 In 2.3.1 (p. 51) we noted that there are two exceptions to the rule that the type of a reference must match the type of the object to which it refers. The first exception is that we …...

Ubuntu2404装机指南

因为原来的2204升级到2404后直接嘎了&#xff0c;于是要重新装一下Ubuntu2404 Ubuntu系统下载 | Ubuntuhttps://cn.ubuntu.com/download我使用的是balenaEtcher将iso文件烧录进U盘后&#xff0c;使用u盘安装&#xff0c;默认选的英文版本&#xff0c; 安装后&#xff0c;安装…...

职坐标:智慧城市未来发展的核心驱动力

内容概要 智慧城市的演进正以颠覆性创新重构人类生存空间&#xff0c;其发展脉络由物联网、人工智能与云计算三大技术支柱交织而成。这些技术不仅推动城市治理从经验决策转向数据驱动模式&#xff0c;更通过实时感知与智能分析&#xff0c;实现交通、能源等领域的精准调控。以…...

DAY 45 leetcode 28的kmp算法实现

KMP算法的思路 例&#xff1a; 文本串&#xff1a;a a b a a b a a f 模式串&#xff1a;a a b a a f 两个指针分别指向上下两串&#xff0c;当出现分歧时&#xff0c;并不将上下的都重新回退&#xff0c;而是利用“next数组”获取已经比较过的信息&#xff0c;上面的指针不…...

从代码学习深度学习 - 自注意力和位置编码 PyTorch 版

这里写自定义目录标题 前言一、自注意力:Transformer 的核心1.1 多头注意力机制的实现1.2 缩放点积注意力1.3 掩码和序列处理1.4 自注意力示例二、位置编码:为序列添加位置信息2.1 位置编码的实现2.2 可视化位置编码总结前言 深度学习近年来在自然语言处理、计算机视觉等领域…...

设计和实现一个基于 DDS(直接数字频率合成) 的波形发生器

设计和实现一个基于 DDS&#xff08;直接数字频率合成&#xff09; 的波形发生器 1. 学习和理解IP软核和DDS 关于 IP 核的使用方法 IP 核&#xff1a;在 FPGA 设计中&#xff0c;IP 核&#xff08;Intellectual Property Core&#xff09;是由硬件描述语言&#xff08;HDL&a…...

AWS IAM权限详解:10个关键权限及其安全影响

1. 引言 在AWS (Amazon Web Services) 环境中,Identity and Access Management (IAM) 是确保云资源安全的核心组件。本文将详细解析10个关键的IAM权限,这些权限对AWS的权限管理至关重要,同时也可能被用于权限提升攻击。深入理解这些权限对于加强AWS环境的安全性至关重要。 2.…...

UniRig ,清华联合 VAST 开源的通用自动骨骼绑定框架

UniRig是清华大学计算机系与VAST联合开发的前沿自动骨骼绑定框架&#xff0c;专为处理复杂且多样化的3D模型而设计。基于强大的自回归模型和骨骼点交叉注意力机制&#xff0c;UniRig能够生成高质量的骨骼结构和精确的蒙皮权重&#xff0c;大幅提升动画制作的效率和质量。 UniR…...

DELL电脑开机进入自检界面

疑难解答 - 如何解决开机直接进入BIOS画面 添加链接描述 一、DELL电脑开机自检提示please run setup program 未设置一天中的时间-请运行安装程序(Time-of-day not set - please run SETUP program) 配置信息无效-请运行安装程序(Invalid configuration information - ple…...

分库分表-除了hash分片还有别的吗?

在分库分表的设计中,除了常见的 Hash 分片,还有多种策略根据业务场景灵活选择。以下是几种主流的分库分表策略及其应用场景、技术实现和优缺点分析,结合项目经验(如标易行投标服务平台的高并发场景)进行说明: 一、常见分库分表策略 1. 范围分片(Range Sharding) 原理:…...

Spring Cloud初探之使用load balance包做负载均衡(三)

一、背景说明 基于前一篇文章《Spring Cloud初探之nacos服务注册管理(二)》&#xff0c;我们已经将服务注册到nacos。接下来继续分析如何用Spring cloud的load balance做负载均衡。 load balance是客户端负载均衡组件。本质是调用方拿到所有注册的服务实例列表&#xff0c;然…...

MySQL 数据库备份和恢复全指南

MySQL 是一款常用的开源数据库系统&#xff0c;在日常运维中&#xff0c;数据备份和恢复是系统管理的重要一环。本文将细致介绍 MySQL 两大备份方案—— mysqldump 和 XtraBackup&#xff0c;包括备份方式、恢复步骤、定时脚本、远程备份和常见问题处理方案。 一、mysqldump 备…...

Linux 命令全解析:从零开始掌握 Linux 命令行

Linux 作为一款强大的开源操作系统&#xff0c;广泛应用于服务器、嵌入式系统以及超级计算机领域。掌握 Linux 命令行技能&#xff0c;是每一位开发者和系统管理员的必备能力。本文将从基础开始&#xff0c;为你详细介绍常用的 Linux 命令&#xff0c;以及它们的使用场景和示例…...

vector常用的接口和底层

一.vector的构造函数 我们都是只讲常用的。 这四个都是比较常用的。 第一个简单来看就是无参构造&#xff0c;是通过一个无参的对象来对我们的对象进行初始化的&#xff0c;第一个我们常用来当无参构造来使用。 第二个我们常用的就是通过多个相同的数字来初始化一个vector。 像…...

VMware安装Ubuntu实战分享

1.前期准备 1. 硬件要求 确保您的计算机满足以下基本硬件要求&#xff0c;以便顺利运行 VMware 和 Ubuntu&#xff1a; 处理器&#xff1a; 至少支持虚拟化技术&#xff08;如 Intel VT-x 或 AMD-V&#xff09;。可以在 BIOS 设置中启用此功能。 内存&#xff1a; 至少 4GB …...

解锁Grok-3的极致潜能:高阶应用与创新实践

引言 Grok-3&#xff0c;作为xAI公司推出的第三代人工智能模型&#xff0c;以其强大的推理能力和多模态处理能力在全球AI领域掀起了热潮。不仅在数学、科学和编程等基准测试中超越了众多主流模型&#xff0c;其独特的DeepSearch和Big Brain模式更赋予了它处理复杂任务的卓越性…...

【2025年3月中科院1区SCI】Rating entropy等级熵及5种多尺度,特征提取、故障诊断新方法!

引言 2025年3月&#xff0c;研究者在国际机械领域顶级期刊《Mechanical Systems and Signal Processing》&#xff08;JCR 1区&#xff0c;中科院1区 Top&#xff0c;IF&#xff1a;7.9&#xff09;上以“Rating entropy and its multivariate version”为题发表科学研究成果。…...

【AI学习】李宏毅老师讲AI Agent摘要

在b站听了李宏毅2025最新的AI Agent教程&#xff0c;简单易懂&#xff0c;而且紧跟发展&#xff0c;有大量最新的研究进展。 教程中引用了大量论文&#xff0c;为了方便将来阅读相关论文&#xff0c;进一步深入理解&#xff0c;做了截屏纪录。 同时也做一下分享。 根据经验调整…...

Nacos-Controller 2.0:使用 Nacos 高效管理你的 K8s 配置

作者&#xff1a;濯光、翼严 Kubernetes 配置管理的局限 目前&#xff0c;在 Kubernetes 集群中&#xff0c;配置管理主要通过 ConfigMap 和 Secret 来实现。这两种资源允许用户将配置信息通过环境变量或者文件等方式&#xff0c;注入到 Pod 中。尽管 Kubernetes 提供了这些强…...

小程序获取用户总结(全)

获取方式 目前小程序获取用户一共有3中(自己接触到的),但由于这个API一直在改,所以不确定后期是否有变动,还是要多关注官方公告。 方式一 使用wx.getUserInfo 实例: wxml 文件<button open-type="getUserInfo" bindgetuserinfo="onGetUserInfo&quo…...

SQL(2):SQL条件判断、排序、插入、更新、删除

1、满足条件 AND和OR&#xff0c;简单 SELECT * FROM 表 WHERE countryCN AND alexa > 50;SELECT * FROM Websites WHERE countryUSA OR countryCN;2、排序&#xff0c;掌握&#xff1a;<order by&#xff0c;降序怎么表示> 就没问题 默认升序&#xff0c;ASC表示升…...

玩转Docker | 使用Docker部署Xnote笔记工具

玩转Docker | 使用Docker部署Xnote笔记工具 前言一、Xnote介绍Xnote简介1.2 Xnote特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署Xnote服务下载镜像编辑配置文件编辑部署文件创建容器检查容器状态检查服务端口安全设置四、访问Xnote服务访问Xnote首页…...

RPCRT4!OsfCreateRpcAddress函数分析之AssociationBucketMutexMemory数组的填充

第一部分&#xff1a; 1: kd> p RPCRT4!OsfCreateRpcAddress0x28: 001b:77c0f4f5 e888e5ffff call RPCRT4!OSF_ADDRESS::OSF_ADDRESS (77c0da82) 1: kd> t RPCRT4!OSF_ADDRESS::OSF_ADDRESS: 001b:77c0da82 ?? ??? 1: kd> kc # 00 RPCRT4!…...

【BUG】Redis RDB快照持久化及写操作禁止问题排查与解决

1 问题描述 在使用Redis 的过程中&#xff0c;遇到如下报错&#xff0c;错误信息是 “MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk...”&#xff0c;记录下问题排查过程。 2 问题排查与解决 该错误提示表明&#…...

conda如何安装和运行jupyter

在Conda环境中安装和运行Jupyter Notebook是一项常见且实用的任务&#xff0c;特别是在数据科学和机器学习项目中。以下是使用Conda安装和运行Jupyter Notebook的步骤&#xff1a; 安装Jupyter Notebook 首先&#xff0c;确保你的Conda是最新的。打开终端或Anaconda Prompt&a…...

java分页实例

引言 在现代Web应用和移动应用中&#xff0c;面对大量数据的展示&#xff0c;分页技术成为了提升用户体验和优化数据加载效率的关键手段。尤其是在MySQL数据库环境中&#xff0c;合理运用分页查询不仅能显著减少服务器负载&#xff0c;还能提升数据访问速度&#xff0c;为用户提…...

android 实现头像堆叠效果

1&#xff1a;依赖 implementation ("com.github.bumptech.glide:glide:4.12.0") annotationProcessor ("com.github.bumptech.glide:compiler:4.12.0") 第一种方式&#xff0c;布局创建frameLayout使用动态添加view方式实现 <FrameLayout and…...

【Linux篇】ELF文件及其加载与动态链接机制

ELF文件及其加载与动态链接机制 一. EFL文件1.1 ELF文件结构二. ELF文件形成与加载2.1 ELF形成可执行2.2 ELF控制性文件的加载2.2.1总结 三. ELF加载与进程地址空间3.1 动态链接与动态库加载3.1.1 进程如何看到动态库 3.2 全局偏移量表GOT(global offset table&#xff09;3.2.…...

经典算法 判断一个图中是否有环

判断一个图中是否有环 问题描述 给一个以0 0结尾的整数对列表&#xff0c;除0 0外的每两个整数表示一条连接了这两个节点的边。假设节点编号不超过100000大于0。你只要判断由这些节点和边构成的图中是否存在环。存在输出YES&#xff0c;不存在输出NO。 输入样例1 6 8 5 3 …...

AI与深度伪造技术:如何识别和防范AI生成的假视频和假音频?

引言&#xff1a;深度伪造的崛起 近年来&#xff0c;人工智能技术迅猛发展&#xff0c;其中深度伪造&#xff08;Deepfake&#xff09; 技术尤为引人注目。这项技术利用深度学习和神经网络&#xff0c;可以轻松生成高度逼真的假视频和假音频&#xff0c;使人物的面部表情、语音…...