【C++】优化函数对象:提升性能和内存效率

2024-09-07 17:52

本文主要是介绍【C++】优化函数对象:提升性能和内存效率,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 函数对象 =》c语言里面的函数指针
  • 对象构造优化
  • 对象使用过程中背后调用的方法
  • 函数调用过程中对象背后调用方法:
  • 优化原则
  • move,forward

函数对象 =》c语言里面的函数指针

  1. 通过函数对象调用operator(),可以省略函数的调用开销,比通过函数指针调用函数(不能够inline内联调用)效率高
  2. 因为函数对象是用类生成的,所有还可以添加相关的成员变量,用来记录函数对象使用时的更多信息。
  • 使用函数对象
template<typename T>
class mygreater
{
public:bool operator()(T a,T b){return a > b;}
};
template<typename t>
class myless
{
public:
bool operator()(t a,t b)
{
return a < b;
}
};
  • 使用C语言的函数指针
template<typename T>
inline bool mygreater(T a, T b)
{
return a > b;
}
template<typename T>
inline bool myless(T a, T b)
{
return a < b;
}
template<typename T,typename Compare>
bool compare(T a,T b,Compare comp)
{
//通过函数指针调用函数,是没有办法内联的,效率低,因为有函数调用开销
return comp(a,b);//operator()(a,b)
}

把有operator()小括号运算符重载函数的对象,称作函数对象,或者称作仿函数。

对象构造优化

Test(20) 显示生成临时对象 生存周期 :所在语句
C++编译对于对象构造的优化:用临时对象生成新对象的时候,临时对象就不产生了,直接构造新对象就是可以了。
Test t4(20); == Test t4 = Test(20);
//显示生成临时对象
t4 = Test(30);
t4 = (Test)30;
//隐式生成临时对象
t4 = 30;
Test *p = &Test(20);
//p指向的是一个已经析构的临时对象
const Test &ref = Test(30);

对象使用过程中背后调用的方法

Test t1(10,10); //1.Test(int,int)
int main()
{
Test t2(20,20); //3.Test(int,int)
Test t3 = t2;   //4.Test(const Test&)
static Test t4 = Test(30,30); //5.Test(int,int)
t2 = Test(20,30); //6.Test(int,int) operator= ~Test()
t2 = (Test)(30,30);//7.Test(int,int) operator= ~Test()
t2 = 6;			//8.Test(int,int) operator=~Test()
Test* p1 = new Test(30,3); //9.Test(int,int)
Test* p2 = new Test[2]; 	//10.Test(int,int) Test(int,int)
Test* p3 = &Test(60,60);  	//11.Test(int,int) ~Test()
const Test &p4 = Test(30,30); //12.Test(int,int)
delete p1;					//13~Test()
delete []p2;				//14.~Test() ~Test()
return 0;
}
Test t5(100,1000); //2.Test(int,int)//注意:5,4,1最后析构

函数调用过程中对象背后调用方法:

Test function(Test t)  	//3.Test(const Test&)
{
int val = t.getDaa();
Test tmp(val);	//4.Test(int)return tmp; 	//5.Test(const Test&)	在主函数中构造一个临时函数对象//6.~Test()//7.~Test()
}
int main()
{
Test t1; //1.Test(int)
Test t2;//2.Test(int)
t2  = function(t1);
//函数调用,实参到形参,是初始化,不是赋值//8. operator = //9.~Test() 析构5.的临时对象//10.~Test()析构2.对象//11.~Test()析构1.对象
return 0;
}

优化原则

  1. 优化一:
Test function(Test &t)  	
{
int val = t.getDaa();
Test tmp(val);	//3.Test(int)return tmp; 	//4.Test(const Test&)	在主函数中构造一个临时函数对象//5.~Test()}
int main()
{
Test t1; //1.Test(int)
Test t2;//2.Test(int)
t2  = function(t1);
//函数调用,实参到形参,是初始化,不是赋值//6. operator = //7.~Test() 析构4.的临时对象//8.~Test()析构2.对象//9.~Test()析构1.对象
return 0;
}
  1. 优化二:
Test function(Test &t)  	
{
int val = t.getDaa();			
return Test(val); 	//在主函数中直接构造一个函数对象(用临时对象构造一个新对象)//3.Test(int)不会先进行拷贝构造,	
}
int main()
{
Test t1; //1.Test(int)
Test t2;//2.Test(int)
t2  = function(t1);//4. operator = //5.~Test() 析构3.的临时对象//6.~Test()析构2.对象//7.~Test()析构1.对象
return 0;
}
  1. 优化三:
Test function(Test &t)  	
{
int val = t.getDaa();			
return Test(val); //2.Test(int) 直接构造t2		
}
int main()
{
Test t1; //1.Test(int)
Test t2 = function(t1);//又是临时对象拷贝构造同类型的新对象t2//3.~Test()析构2.对象//4.~Test()析构1.对象
return 0;
}
  1. 总结优化:
    4.1.函数参数传递过程中,对象优先按引用传递,不要按值传递
    42.函数返回对象的时候,应该优先返回一个临时对象,而不是一个定义过的对象
    4.3.接收返回值是对象的函数调用的时候,优先按初始化的方式接受,而不是按赋值的方式接收。

move,forward

  • std::move:支持移动语义
    std::move 是一个模板函数,位于 头文件中。
    它接受一个对象,并将其转换为右值引用(把左值转换成右值),使得该对象可以被移动而非复制。
    使用 std::move 可以显式地表明程序员希望将对象的所有权从一个对象转移到另一个对象,通常用于在移动语义中。
    std::move 并不会移动任何数据,它只是将一个对象标记为可移动的,告诉编译器在适当的情况下使用移动语义。
    使用 std::move 后,原对象的状态可能会被视为未定义,因此使用后需要谨慎处理原对象。
    示例:
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination = std::move(source); // 移动 source 到 destination
  • std::forward:完美转发
    std::forward 也是一个模板函数,位于 头文件中。
    它用于完美转发,即在函数模板中保持参数的原始类型(左值引用或右值引用)。
    通常在泛型编程中使用,用于将参数传递给其他函数,并保持其原始的左值或右值特性。
    std::forward 是为了解决函数参数的引用折叠规则而引入的,可以在转发时正确地保持参数的左值或右值特性。
    使用 std::forward 可以确保参数的类型在转发时得到正确保持,从而避免不必要的拷贝或移动操作。
    示例:
template<typename T>
void process(T&& arg) {another_function(std::forward<T>(arg)); // 保持参数 arg 的原始类型(左值引用或右值引用)
}
  • 综上所述,std::move 用于将对象转换为右值,支持移动语义,而 std::forward 则用于在泛型编程中保持参数的原始类型,支持完美转发。这两个函数在现代 C++ 编程中都扮演着重要的角色,用于优化性能并支持通用代码。

这篇关于【C++】优化函数对象:提升性能和内存效率的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�