一、基本定义

关键字含义出现版本
auto根据初始化表达式自动推导类型C++11
decltype根据表达式的类型推导类型C++11

二、二者区别

特性autodecltype(expr)
用途声明变量获取表达式类型
是否需要初始化否(可用表达式,如函数参数)
是否推导引用否(默认忽略引用)是(保持表达式的原始类型,包括引用/const)
典型场景迭代器、lambda 返回值、结构成员等模板返回类型、表达式类型检查等

三、典型示例:autodecltype 区别

int x = 10;
int& rx = x;
const int cx = 20;auto a = rx;         // int(引用被忽略)
decltype(rx) b = x;  // int&(保持引用)auto c = cx;         // int(const 被忽略)
decltype(cx) d = x;  // const int(保持 const)decltype((x)) e = x; // int&(注意括号!表达式是左值 -> 引用)

结论:

  • auto 去掉引用/const
  • decltype(expr) 保持原样
  • decltype((x)) 加括号代表“表达式本身”(是左值引用)

四、混合用法:模板返回值推导

使用 decltype 获取表达式返回类型

template <typename T1, typename T2>
auto add(T1 a, T2 b) -> decltype(a + b) {return a + b;
}

推导返回值为 a + b 的类型,比如 int + double = double


使用 decltype(auto) 保留类型精度(含引用)

int x = 42;
int& rx = x;auto a = rx;         // int
decltype(auto) b = rx;  // int&

decltype(auto) 可用于函数返回值,保留精度和引用性。


示例:使用 decltype(auto) 返回左值引用

int& get_ref(int& x) {return x;
}decltype(auto) test() {int y = 10;return (y); // 返回 int&
}

如果你写 auto test() { return (y); },将返回 int 值(临时副本)


五、与模板结合的应用

1. 泛型访问容器元素(防止引用丢失)

template<typename Container, typename Index>
decltype(auto) get(Container&& c, Index i) {return std::forward<Container>(c)[i];
}
  • 保证返回值可以是 int&const int&、或 int
  • 适用于完美转发与引用保持

2. 推导 lambda 返回值类型

auto lambda = [](auto a, auto b) -> decltype(a + b) {return a + b;
};

如果写 auto lambda = [](auto a, auto b) { return a + b; };,则 C++14 之后自动推导返回类型;否则需显式写出。


六、标准库场景中的推导技巧

std::vector::emplace_back 的返回值

std::vector<std::pair<int, int>> v;
auto& ref = v.emplace_back(1, 2);

若写作:

decltype(auto) ref = v.emplace_back(1, 2); // ref 是 pair<int, int>&

decltype(auto) 保证类型不丢失引用。


七、常见陷阱

错误模式解释
auto 丢失引用auto a = ref;a 是值,不再是引用
decltype(x)decltype((x)) 区别x 是值类型,(x) 是左值表达式 → int&
返回局部变量引用(未捕获 const/引用)auto 返回会拷贝,生命周期易出错

八、示例代码完整演示

#include <iostream>
#include <vector>
#include <type_traits>int add(int a, int b) { return a + b; }template <typename T1, typename T2>
auto generic_add(T1 a, T2 b) -> decltype(a + b) {return a + b;
}int main() {int x = 5;const int cx = 10;int& rx = x;auto a = cx;            // intdecltype(cx) b = cx;    // const intdecltype((x)) c = x;    // int&decltype(auto) d = rx;  // int&std::cout << std::boolalpha;std::cout << "is_reference<decltype(a)>: " << std::is_reference<decltype(a)>::value << "\n";std::cout << "is_reference<decltype(b)>: " << std::is_reference<decltype(b)>::value << "\n";std::cout << "is_reference<decltype(c)>: " << std::is_reference<decltype(c)>::value << "\n";std::cout << "is_reference<decltype(d)>: " << std::is_reference<decltype(d)>::value << "\n";auto res = generic_add(1, 2.5); // doublestd::cout << "Result: " << res << std::endl;
}

九、总结对比表

用法autodecltypedecltype(auto)
推导变量类型✅(表达式类型)
保留引用/const❌ 默认去掉
可用于函数返回值
是否能表达复杂表达式类型❌ 一般✅(适合模板表达式)

十、在 STL 泛型算法中的应用

示例 1:推导 std::vector 的元素类型

template <typename Container>
void print_first(const Container& c) {// auto elem = c[0];             // 拷贝,丢失引用decltype(auto) elem = c[0];      // 正确保持类型std::cout << elem << std::endl;
}

这样可以正确保持 const&,比如对 std::vector<const int&> 也能正常工作。


示例 2:遍历容器的推荐写法

template <typename Container>
void iterate(const Container& c) {for (decltype(auto) val : c) {// val 会是值,不能用于修改}for (decltype(auto) val : c) {// 如果 c 是 vector<int&>,则 val 为 int&}for (auto& val : c) {// 修改 val 正确}
}

推荐使用 auto&decltype(auto) 保证类型精度(尤其修改容器时)


十一、Lambda 中自动类型推导

示例:Lambda 参数、返回值自动推导

auto lambda = [](auto a, auto b) {return a + b; // C++14 自动推导返回值
};

显式返回值类型(需要引用、const 保留)

auto lambda = [](auto& a, auto& b) -> decltype(auto) {return (a < b) ? a : b;  // 返回引用
};

若使用 auto,返回的是值拷贝,而非引用。


十二、结合类型萃取(std::remove_reference 等)

类型萃取技术与类型推导结合,可实现更加通用和安全的泛型逻辑。

示例:移除引用以构建值类型容器

template<typename T>
using PureType = typename std::remove_reference<T>::type;template <typename T>
void store_copy(T&& val) {using T_clean = PureType<T>;std::vector<T_clean> vec;vec.push_back(std::forward<T>(val));
}

示例:获得成员类型

template<typename Container>
void print_value_type(const Container& c) {using ValueType = typename std::remove_cv<typename std::remove_reference<decltype(*c.begin())>::type>::type;std::cout << "Value type: " << typeid(ValueType).name() << std::endl;
}

十三、decltype 用于 SFINAE 和模板 enable_if

template <typename T>
auto test(T x) -> decltype(x.begin(), void()) {std::cout << "Has begin()" << std::endl;
}

用于判断类型是否有某成员函数,配合 std::enable_if 实现 SFINAE。


十四、配合返回值类型推导的通用库设计

封装函数组合器(函数链式组合)

template<typename F1, typename F2>
auto compose(F1 f, F2 g) {return [=](auto x) -> decltype(auto) {return f(g(x));};
}

返回值使用 decltype(auto),确保引用/const 等信息不丢失。


十五、decltype(auto) vs auto 总结对比(表格)

情景autodecltype(auto)
值语义返回
保留引用语义(如返回 int&❌(变成 int✅(保持 int&
保留 const❌(变成普通类型)✅(保持 const int / const&)
用于模板函数返回值❌ 不推荐✅ 推荐

十六、实际场景最佳实践推荐

场景推荐写法
遍历并修改容器for (auto& x : container)
函数返回引用或 constdecltype(auto)
泛型函数返回值依赖表达式类型-> decltype(expr)decltype(auto)
完美转发保持类型T&& + decltype(auto)
获取表达式类型decltype(expr)

十七、小结与建议

  • 优先使用 auto 简化类型声明(值类型需求)
  • 使用 decltype(auto) 保留返回值或变量的精确类型(引用、const)
  • 谨慎使用 decltype(expr),注意是否加括号 (expr) 会影响推导结果
  • 与类型萃取库配合使用(如 std::remove_reference)提升类型控制能力
  • 在模板中,函数返回值推荐使用 trailing return + decltype

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

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

相关文章

Echarts数据可视化开发教程+120套开源数据可视化大屏H5模板

数据可视化跨越了语言、技术和专业的边界&#xff0c;是能够推动实现跨界沟通&#xff0c;实现国际间跨行业的创新的工具。 正如画家用颜料表达自我&#xff0c;作者用文字讲述故事&#xff0c;而统计人员用数字沟通 ...... 同样&#xff0c;数据可视化的核心还是传达信息。 …

华为提取版,低调使用!

大家好呀&#xff01;今天想给大家推荐两款实用软件&#xff0c;一个是视频软件的定制版&#xff0c;另一个是卫星地图软件。 01 引言 之前给大家推荐过某秋音乐的定制版&#xff0c;结果被投诉了。以后大家推荐某秋家的软件要小心&#xff0c;不然很容易违规。 今天推荐的是…

天汇企业的网络设计与实现

天汇企业网络的设计与实现 摘要&#xff1a;互联网技术与通信技术的相互带动作用&#xff0c;使得两者皆呈现多样化的快速发展趋势&#xff0c;5G的时代序幕在已经逐渐开启&#xff0c;由此引发的互联网技术和设备变革必然是各界人士关注的重点&#xff0c;几乎所有与计算机相…

系统架构设计师:安全架构考点解析与例题

一、安全架构概述 安全架构是系统架构设计中确保信息系统安全性的重要组成部分,它定义了保护系统免受安全威胁的策略、技术和方法。安全架构需要贯穿系统设计的全生命周期,从需求分析到部署运维。 安全架构核心目标 ​​保密性​​:防止未授权访问信息​​完整性​​:防止…

计量经济学(复习/自用/未完)

补充&#xff1a; 1、多重共线性的补充 所谓的估计标准误&#xff0c;指的是回归系数的标准误差。例如回归方程&#xff1a; y β0 β1X1 β2X2 e 我们构建的回归方程的系数的计算得出是基于样本的。这意味着&#xff0c;我们每从总体中进行一次抽样&#xff0c;然后计算…

HarmonyOS性能优化——感知流畅优化

在应用开发中&#xff0c;动画可以为用户界面增添生动、流畅的交互效果&#xff0c;提升用户对应用的好感度。然而&#xff0c;滥用动画也会导致应用性能下降&#xff0c;消耗过多的系统资源&#xff0c;甚至影响用户体验。关于感知流畅度请参阅提升动画感知流畅度。 视觉感知…

基于Python的房屋信息可视化及价格预测系统

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.10(必须)数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat12开发软件&#xff1a;PyCharm 系统展示 系统首页 系统登录 房价预测 房屋管理 房屋分析 个人信息 密码修改 用户管理 摘…

(17)-java+ selenium->自动化测试-元素定位大法之By css上

1.简介 CSS定位方式和xpath定位方式基本相同,只是CSS定位表达式有其自己的格式。CSS定位方式拥有比xpath定位速度快,且比CSS稳定的特性。下面详细介绍CSS定位方式的使用方法。相对CSS来说,具有语法简单,定位速度快等优点。 2.CSS定位优势 CSS定位是平常使用过程中非常重要…

高效I/O处理:模型与多路复用的探讨

目录 一、了解IO模型 &#xff08;一&#xff09;异步IO和同步IO &#xff08;二&#xff09;五种IO快速回顾 二、IO多路复用 &#xff08;一&#xff09;IO 多路复用模型 &#xff08;二&#xff09;select 实现原理 &#xff08;三&#xff09;poll 实现原理 &#x…

行列式展开定理(第三种定义) 线性代数

目录 1.余子式 2代数余子式 3行列式展开公式&#xff08;常用&#xff09; 本篇的用途是关于三阶以上行列式的一般解法。因为对于三阶以上行列式我们没有类似于2阶和三阶一样的特殊的求值办法&#xff0c;而对于我们上一篇讲的办法来说又太复杂了&#xff0c;一般考试几乎不…

一种轻量级IDS,使用新型特征选择方法进行早期APT检测

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 高级持续性威胁 (APT) 是一种多阶段、高度复杂且隐蔽的网络威胁形式&#xff0c;它通过获得对网络的未授权访问来窃取有价值的数据或破坏目标网络。这些威胁通常在很长一段时间内未被发现&#xff0c;这…

深入理解 let、var 和 const

JavaScript 中的变量声明有三种主要方式&#xff1a;var、let 和 const。理解它们之间的差异对于编写清晰、有效的代码至关重要。本文将深入探讨这三种声明方式的区别、使用场景以及潜在的陷阱。 一、var 关键字 1.1 特点 函数作用域&#xff1a;var 声明的变量在函数内是局…

RT thread 在gd32f303平台下rtc bug date获取时间错误始终是1970

现象 时间设置指令 date 2025 6 18 10 28 00 时间获取指令 date date指定显示设置OK,但是返回的时间始终是Thu Jan 1 08:00:00 1970 msh >date local time: Thu Jan 1 08:00:00 1970 timestamps: 0 timezone: UTC+

jieba中lcut与cut的区别及用法

jieba 库中的 cut 和 lcut 是中文分词的核心函数&#xff0c;两者的核心区别在于​​返回类型​​和​​适用场景​​&#xff0c;具体对比如下&#xff1a; ⚙️ 1. ​​核心区别​​ ​​函数​​​​返回类型​​​​特点​​​​等价操作​​jieba.cut生成器&#xff08;G…

LoRA、QLoRA是什么

一&#xff1a; LoRA&#xff08;Low-Rank Adaptation&#xff0c;低秩适应&#xff09;是一种高效的大模型参数微调技术&#xff0c;由Meta在2021年提出。它通过冻结预训练模型参数&#xff0c;仅训练少量新增的低秩矩阵&#xff0c;大幅减少了需要训练的参数量&#xff0c;同…

【web应用】在 Vue 3 中实现饼图:使用 Chart.js实现饼图显示数据分析结果

文章目录 前言一、准备工作二、实现饼图组件三、关键点解析四、实现效果总结 前言 在现代 Web 应用中&#xff0c;数据可视化是不可或缺的一部分。无论是展示统计信息还是监控关键指标&#xff0c;图表都能帮助用户更直观地理解数据。在 Vue 3 项目中&#xff0c;我们可以使用…

分页数据不准问题分析与解决

大纲 &#x1f4d6; 1、场景 &#x1fab5;2、原因 &#x1f525;3、解决方式&#xff1a;游标分页 &#x1f4cf;4、一点思考&#x1f4a1;5、全表查询的优化思路 &#x1f345; 记录一个分页不准的问题 1、场景 &#x1fab5; 调用一个第三方List接口&#xff08;带分页&am…

MyBatis原理剖析(三)--加载配置文件

下面我们正式进入mybatis的源码学习&#xff0c;之前我们已经了解过mybatis中通过配置文件来保证与数据库的交互。配置文件分为核心配置文件和映射配置文件&#xff0c;核心配置文件的主要作用就是加载数据库的一些配置信息而映射配置文件则是执行对应的sql语句。同时核心配置文…

C++(运算符重载)

一.友元 C中使用关键字friend可以在类外访问所有的成员&#xff0c;包括私有成员&#xff08;之前提到过封装的核心思想是隐藏内部实现细节&#xff0c;通过公共接口控制访问&#xff09;&#xff0c;所以友元可以突破封装的限制访问数据&#xff0c;盲目使用会导致程序稳定性…

XR-RokidAR-UXR3.0-Draggable 脚本解析

using System.Collections.Generic; using Rokid.UXR.Utility; using UnityEngine; using UnityEngine.EventSystems;namespace Rokid.UXR.Interaction {/// <summary>/// Draggable 拖拽组件/// </summary>// [RequireComponent(typeof(RayInteractable))]public …