将与参数无关的代码抽离templates——条款44

基于卷积神经网络的人脸识别算法 摘要:近年来,随着科学技术的不断发展,人脸识别技术日渐成熟,使得人脸识别技术的使用率不断增大。例如:门禁、ATM机、公安系统以及新兴起的人机交互等领域,都应用到了人脸识别系统。在人脸识别研究领域中,深度学习扮演着重要的角色。由于深度学习的人脸识别技术凭借其识别率高、识别快等特点,逐渐成为整个领域的主流技术。在众多深度学习算法中,以卷积神经网络为代表的人脸识别系统得到了广泛应用,主要研究内容如下:首先,通过对经典损失函数进行研究,对比每种损失函数的特点,然后根据A-Softmax函数进行改进,借助Margin 阅读详情

        Templates是节省时间和避免代码重复的一个奇方妙法。不再需要键入20个类似的classes而每一个带有15个成员函数,你只需键入一个class template,留给编译器去具现化那20个你需要的相关classes和300个函数。(class templates的成员函数只有在被使用时才被暗中具现化,所以只有在这300个函数的每一个都被使用,你才会获得这300个函数。)Function templates有类似的诉求。替换写许多函数,你只需要写一个function templates,然后让编译器做剩余的事情。

        有时候,如果你不小心,使用templates可能会导致代码膨胀:其二进制码带着重复(或几乎重复)的代码、数据,或两者。其结果又可能源码看起来合身而整齐,但目标码(object code)却不是那么回事。

        当你编写某个函数,而你明白其中某些部分的实现码和另一个函数的实现码实质相同,你会很单纯地重复这些码码?当然不。你会抽出两个函数的共同部分,把它们放进第三个函数中,然后令原先两个函数调用这个新函数。也就是说,你分析了两个函数,找出共同的部分和变化的部分,把共同部分搬到一个新函数去,保留变化的部分在原函数中不动。

        编写templates时,也是做相同的分析,以相同的方式避免重复,但其中有个窍门。在non-template代码中,重复十分明确:你可以“看”到两个函数或两个classes之间有所重复。然而在template代码中,重复是隐晦的:毕竟只存在一份template源码,所以你必须训练自己去感受当template被具现化多次时可能发生的重复。

        举个例子,假设你想为固定尺寸的正方矩阵编写一个template。该矩阵的性质之一是支持逆矩阵运算。

template<typename T, std::size_t n>
class SquareMatrix {
public:
    ...
    void invert();        // 求逆矩阵
};

        这个template接受一个类型参数T,除此之外还接受一个类型为size_t的参数,那是个非类型参数。这种参数和类型参数比起来较不常见,但它们完全合法,而且就像本例一样,相当自然。

        现在,考虑这些代码:

SquareMatrix<double,5> sml;
...
sm1.invert();                     // 调用SquareMatrix<double,5>::invert
SquareMatrix<double,10> sm2;
...
sm2.invert();                     // 调用SquareMatrix<double,10>::invert

        这回具现化两份invert。这些函数并非完完全全相同,因为其中一个操作的是5*5矩阵而另一个操作的是10*10矩阵,但除了常量5和10,两个函数的其他部分完全相同。这是template引出代码膨胀的一个典型例子。

        如果你看到两个函数完全相同,只除了一个使用5而另一个使用10,你会怎么做?你的本能会为它们建立一个带数值参数的函数,然后以5和10来调用这个带参数的函数,而不重复代码。下面是对SquareMatrix第一次修改:

template<typename T>
class SquareMatrixBase {
protected:
    ...
    void invert(std::size_t matrixSize);    // 以给定的尺寸求逆矩阵
    ...
};

template<typename T, std::size_t n>
class SquareMatrix: private SquareMatrixBase<T> {
private:
    using SquareMatrixBase<T>::invert;     // 避免遮掩base班的invert;见条款33
public:
    ...
    void invert() { this->invert(n); }    // 制造一个inline调用,调用base class版的invert。
};

        目前为止一切都好,但还有一些棘手的问题没有解决。SquareMatrixBase::invert如何知道该操作什么数据?虽然它从参数中知道矩阵尺寸,但它如何知道哪个特定矩阵的数据在哪儿?想必只有derived class知道。我们可以令SquareMatrixBase贮存一个指针,指向矩阵数值所在的内存。而只要它存储了那些东西,也就可能存储矩阵尺寸。成果看起来像这样:

template<typename T>
class SquareMatrixBase {
protected:
    SquareMatrixBase(std::size_t n, T* pMem)      // 存储矩阵大小和一个指针,指向矩阵数值
    : size(n), pData(pMem) {}
    void setDataPtr(T* ptr) { pData = ptr; }      // 重新赋值给pData
    ...
private:
    std::size_t size;                             // 矩阵大小
    T* pData;                                     // 指针,指向矩阵内容
};

        这允许derived classes决定内存分配方式。某些实现版本也许会决定将矩阵数据存储在SquareMatrix对象内部:

template<typename T, std::size_t n>
class SquareMatrix: private SquareMatrixBase<T> {
public:
    SquareMatrix()                       // 送出矩阵大小和数据指针给base class
    : SquareMatrixBase<T>(n, data) {}
    ...
private:
    T data[n*n];
};

        这种类型的对象不需要动态分配内存,但对象自身可能非常大。另一种做法是每一个矩阵的数据放进heap(也就是通过new来分配内存):

template<typename T, std::size_t n>
class SquareMatrix: private SquareMatrixBase<T> {
public:
    SquareMatrix()                     // 将base class的数据指针设为null,为矩阵内容分配内存
    : SquareMatrixBase<T>(n, 0),       
    pData(new T[n*n])                      // 将指向该内存的指针存储起来,
    { this->setDataPtr(pData.get()); }     // 然后将它的一个副本交给base class
    ...
private:
    bosst::scoped_array<T> pData; 
};

        这个条款只讨论由non-type template parameters(非类型模板参数)带来的膨胀,其实type parameters(类型参数)也会导致膨胀。例如在许多平台上int和long有相同的二进制表述,所以像vector<int>和vector<long>的成员函数有可能完全相同——这正是最佳定义。

请记住

  • Templates生成多个classes和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生相依关系。
  • 因非类型模板参数(non-type template parameters)而造成的代码膨胀,往往可以消除,做法是以函数参数或class成员变量替换template参数。
  • 因类型参数(type parameters)而造成的代码膨胀,往往可降低,做法是让带有完全相同的二进制表述的具现类型共享实现码。
STM32 FOC电机控制:手把手教你用CubeMX配置TIM1中心对齐PWM(含代码避坑) 本文详细解析了STM32 FOC电机控制中TIM1中心对齐PWM的配置方法,涵盖CubeMX图形化设置、HAL库代码调用及常见问题排查。特别针对L6230Q驱动芯片的使能逻辑和死区时间配置提供实用指南,帮助开发者高效实现无刷电机的高性能控制。 阅读详情

相关推荐

支付逻辑漏洞的八大姿势(上篇)

学习支付漏洞,看这篇文章!!!文章来源:SecHub网络安全社区(本资料仅供学习参考,严禁使用者进行未授权渗透测试!严禁任何形式的转载!

qq_39493066的博客 1358

EffectiveC++-条款44:将与参数无关的代码抽离 templates

## 一. 内容 1. `templates 是节省时间和避免代码重复的奇方妙法。`你不再需要键入 20 个类似的 classes 并且每一个都带有 20 个 成员函数,你只需要键入一个 class template,留给编译器去具现化那 20 个你需要的相关 classes 即可,而且对于 20 个函数中未被调用的,编译器不会自动生成。这样的技术是不是很伟大,呵呵。 2. 但是,这也很容易使得代码膨胀(code bloat),templates 产出码带着重复,或者几乎重复的代码,数据,或者两者。你可以通

MoOtA 490

解决TextMeshPro在AB打包中的字体冗余问题:源码修改全记录

本文详细介绍了如何解决TextMeshPro在AB打包中的字体冗余问题,通过源码改造和工程实践优化Unity项目的性能。内容包括资源加载路径重构、AB打包策略优化及运行时加载方案,有效减少包体体积和构建时间,提升内存效率。

weixin_42558257的博客 184

条款44:将与参数无关的代码抽离templates

(1)Template生成多个classes和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生联系;(2)因非类型模板参数而造成的代码膨胀,往往可以消除,做法是以函数参数或class成员变量替换template参数(3)因类型参数(type parameters)而造成的代码膨胀,往往可降低,做法是让带有完全相同二进制表述的具现类型共享实现码。

依然爱猪的博客 1094

InsightFace实战:如何在树莓派上部署轻量级人脸识别系统(附完整代码)

本文详细介绍了如何在树莓派上部署基于InsightFace框架的轻量级人脸识别系统。通过硬件选型、环境配置、模型优化(如MobileFaceNet)及完整代码实战,指导开发者构建本地化、低功耗的智能应用,如智能门铃,并提供了性能调优与系统服务化的进阶技巧。

weixin_29043895的博客 350

《Effective C++》学习笔记(条款44:将与参数无关的代码抽离 templates)

最近开始看《Effective C++》,为了方便以后回顾,特意做了笔记。若本人对书中的知识点理解有误的话,望请指正!!! 模板是节省时间和避免代码重复的好方法: 类模板:只需要实现一个类模板,编译器会具现化类模板里的 成员函数(类模板里的 成员函数只有在被使用时才暗中具现化,所以只有类模板里的 成员函数都被使用,你才能获得类模板里的全部 成员函数) 函数模板:只需要一个函数模板,编译器就能实现许多不同 template参数 的函数 但使用 模板 会导致代码膨胀:其二进制码带着重复的代码、数据、或两者都

ZLX的博客 674

Unity-RetargetPro3-动画插件试用

一个名气大于实战的插件。

大话程序员 710

Item 44:将参数无关代码重构到模板外去

Item 44: Factor parameter-independent code out of templates. 模板是个好东西,你可以在实现类型安全的同时少写很多代码。但模板提供的是编译期的多态, 即使你的代码看起来非常简洁短小,生成的二进制文件也可能包含大量的冗余代码。 因为模板每次实例化都会生成一个完整的副本,所以其中与模板参数无关的部分会造成代码膨胀(code bloat)。

DoronLee的博客 457

17.6 LangSmith 私有化部署实战指南:企业级AI应用的安全基石

LangSmith 私有化部署, 企业级AI开发平台, 数据隐私合规, 混合云架构, 模型监控与审计。

yonggeit的博客 3777

ADS1115 0-10V高精度ADC模块原理图设计,已量产

在水质监测、智能气象站、环境感知等领域,0-10V 电压输出的传感器占据了重要地位。这类传感器输出信号稳定、抗干扰能力强,但对数据采集模块的精度、线性度和易用性提出了严苛要求。本文将深度解析一款专为 0-10V 传感器设计的高精度 ADC 模块,从硬件架构、性能指标到工程化实践,全面呈现其设计思路与核心价值。

不脱发的程序猿 272

条款44:将与参数无关的代码抽离templates

条款44:将与参数无关的代码抽离templates(Factor parameter-independent code out of templates.)内容:     自从我们进入模板编程的第一天,我们就意识到template不仅大大地减少了代码的执行时间,而且能够避免代码潜在的重复.我们不在需要为20个相似的classes而每一个都带有15个成员函数编写独立的一份代码去分别实现,我们只需

scofieldzhu的专栏 1075

prometheus普罗米修斯集监控外部k8s

prometheus普罗米修斯集监控外部k8s

你是我一生的追求 2247

effective c++条款44 将与参数无关的代码抽离templates

effective c++条款44 将与参数无关的代码抽离templates 首先了解这个条款的含义:使用template可能导致代码膨胀,二进制码会带着重复(或者几乎重复)的代码、数据,或两者。其结果有可能源码看起来合身而整齐,但目标码却不是这么回事。所以该条例用于我们解决 template带来的代码膨胀问题。 首先模板参数并不局限于类型,普通值也可以作为模板参数。 当要使用基于值的模板时,必须显示地指定这些值,才能对模板进行实例化,并获得最终代码。 标题中的参数可以指类型参数也可以指非类型参数 先看非类

weixin_46388214的博客 365

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Effective C++ 条款44:将与参数无关的代码抽离templates

Effective_C++_44

君鼎的博客 429

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Effective C++ 条款44:将与参数无关的代码抽离 templates

掌握消除模板代码膨胀的技巧,学习如何将非类型模板参数和类型参数导致的冗余代码抽离出模板

凡人叶枫的博客 163

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Effective C++ 学习笔记 条款44 将与参数无关的代码抽离templates

与 SquareMatrix 一样,SquareMatrixBase 是一个模板,但与 SquareMatrix 不同的是,它仅在矩阵中对象的类型上模板化,而不是在矩阵的大小上。你不需要编写20个相似的类,每个类包含15个成员函数,只需编写一个类模板,然后让编译器为你实例化所需的20个特定类和300个函数即可(类模板的成员函数只有在使用时才会被隐式实例化,所以只有当你确实用到全部300个成员函数时,它们才会被生成)。在编写模板时,你做的是同样的分析,用同样的方式避免重复,但有一个不同之处。

tus00000的博客 323

《Effective C++》读书笔记 条款44:将与参数无关的代码抽离templates

在使用templates时可能会造成代码膨胀,所以要找出相同的部分,但在templates中重复是隐晦的,书上的例子 template&lt;typename T,std::size_t n&gt;//template支持n*n矩阵,元素是的类型为T class SquqreMatrix { public: void invert();//求逆矩阵 } 考虑如下调用 ...

junya_zhang的博客 289

Effective C++条款44:模板与泛型编程之(将与参数无关的代码抽离templates)

待续

董哥的黑板报 1021

Effective C++条款44:模板与泛型编程——将与参数无关的代码抽离templates

一、代码重复与对应策略 对于函数而言 假设我们编写某些函数(不止一个),这些函数当有有部分代码都是相同的,因此我们认为这份代码对于程序来说是重复的 那么此时我可以将这些函数共同的部分抽取出来,然后放在另一个函数中,让原本那些函数调用这个新函数。这样就达到了缩减代码的效果 对于类而言 假设我们在编写一组类,而这些类中有些部分都是相同的,因此我们认为这份代码对于程序来说是重复的 那么此时我们可以将这些类中共同的部分抽取出来,建立一个新类,然后让原本那些类继承于这个新类。这样就达到了缩减代码的效

www_dong的博客 319

effective C++ 条款 44:将与参数无关的代码抽离templates

template是节省时间和避免重复代码的一个奇妙方法。class template的成员函数只有在被使用时才被暗中具现化。function templates有类似的诉求。 但是如果你不小心,使用templates可能导致代码膨胀(code bloat):其二进制代码带着重复(或几乎重复)的代码、数据、或两者。其结果可能源码看起来合身整齐,但目标码却不是那么回事。你需要知道如何...

weixin_30566063的博客 168

条款44:将与参数无关的代码抽离模板(Factor parameter-independent code out of templates)

Effective C++之条款44

weixin_43739503的博客 222

EffectiveC++ 条款44:将与参数无关的代码抽离templates

LIJIWEI0611的博客 159

Effective C++ -----条款44:将与参数无关的代码抽离templates

Templates生成多个classes和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生相依关系。 因非类型模板参数(non-type template parameters)而造成的代码膨胀,往往可消除,做法是以函数参数或class成员变量替换template参数。 因类型参数(type parameters)而造成的代码膨胀,往往可降低,做法是让带有完...

weixin_30791095的博客 102

《Effective C++》学习笔记——条款44

条款44:将与参数无关的代码抽离templates

继续激情,继续奋斗。 759

条款44:将与参数无关的代码抽离template

这里主要说的是,在编译器中,它们是不同的类型,但实际上在二进制表达上,他们是相同的类型,但是链接器没有做去重。比如文中举例,有的机器上,int和long在二进制层面其实是一样的。不同的参数会展开成不同的模板,导致代码膨胀。●这种写法,不同的n,比如SquareMatrix和SquareMatrix,会展开出不同的实现,导致代码膨胀。注意,子类调用基类invert时候,加上了SquareMatrixBase::以表明调用的是基类的invert,不然会出现递归。

qq_15017123的博客 1751
上一篇: 学习处理模板化基类内的名称——条款43
下一篇: 运用成员函数模板接受所有兼容类型——条款45
OODeveloper
博客等级 码龄12年 43粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值