Modern C++——不准确“类型声明”引发的非必要性能损耗

2024-08-26 08:04

本文主要是介绍Modern C++——不准确“类型声明”引发的非必要性能损耗,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大纲

  • 案例
  • 代码地址

C++是一种强类型语言。我们在编码时就需要明确指出每个变量的类型,进而让编译器可以正确的编译。看似C++编译器比其他弱类型语言的编译器要死板,实则它也做了很多“隐藏”的操作。它会在尝试针对一些非预期类型进行相应转换,以符合预期,比如《C++拾趣——类构造函数的隐式转换》中提到的隐式转换。

但是也正因为这些“隐藏”的转换行为,让一些行为超出我们的预期。比如本文提及的案例,就是因为我们声明了一个不准确的类型变量,导致编译器为了让我们代码“合法”,进而做了一些隐式转换,导致程序性能下降。

我们也将通过这个案例,了解C++11引入auto关键字的必要性。

案例

先看下面这段可以运行的代码。

    std::cout << "Create unordered_map" << std::endl;std::unordered_map<Custom, int> unordered_map;unordered_map[std::move(Custom(1))] = 1;unordered_map[std::move(Custom(2))] = 2;unordered_map[std::move(Custom(3))] = 3;std::cout << std::endl << "Traverse unordered_map using std::pair<Custom, int>" << std::endl;for (const std::pair<Custom, int>& pair : unordered_map) {std::cout << pair.first << " " << pair.second << std::endl;}

请问下面的代码有什么性能问题?

可能第一眼看过去,并不能发现它的问题所在。我们将这段代码的运行过程打印出来
在这里插入图片描述
可以发现在遍历的过程中,发生了Custom对象的复制和析构。

如果Custom对象比较大,就会引发性能问题。

这是因为std::unordered_map的Key是const类型,即我们应该如下方式遍历

    for (const std::pair<const Custom, int>& pair : unordered_map) {std::cout << pair.first << " " << pair.second << std::endl;}   

编译器在发现我们没有使用const Custom时,会自己推理并转换以符合我们书写的代码。这样就会导致一次const Custom向Custom复制的一次构造。

正因为这些犄角旮旯的知识导致编写健壮高效的C++代码比较困难。但是在C++11中引入的auto就可以很大的缓解我们的心智负担。我们可以这么写上述代码

    for (const auto& pair : unordered_map) {std::cout << pair.first << " " << pair.second << std::endl;}

这样编译器会帮我们推导出正确的类型。
在这里插入图片描述

代码地址

https://github.com/f304646673/cpulsplus/tree/master/traverse_unordered_map

这篇关于Modern C++——不准确“类型声明”引发的非必要性能损耗的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1108003

相关文章

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

Python中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基