• Effective C++ 条款44


    本节条款的标题是:将与參数无关的代码抽离templates

    学习本节条款首先须要明确一件事情,那就是模板实例化的过程会不会反复?
    我们来举个样例:

    #include<iostream>
    using namespace std;
    
    template <typename T>
    T Try(T m)
    {
        return m;
    }
    
    int main()
    {
        Try(10);
        Try(1);
    }

    我们看以上简单的代码。每一个人都知道模板被调用了两次,是的,这显而易见。但是模板也被实例化了两次吗?其实,模板仅仅实例化了一次。
    我们再举个样例:

    #include<iostream>
    using namespace std;
    
    template <typename T>
    T Try(T m)
    {
        return m;
    }
    
    int main()
    {
        Try(10);
        Try(1.01);//注意!此时是一个double型
    }

    这个时候每一个人都知道模板被调用了两次。模板也被实例化了两次吗?其实,模板确实实例化了两次。

    比較以上两个样例。大家明确了什么?那就是,模板函数的实例化次数和调用次数没有直接关系,而是和调用类型的种类有关。同种类型假设已经调用,模板函数会反复利用上次的实例化样例。而不会又一次分配内存实例化。假设,大家明确这一点本节条款就能理解了。

    我们利用template就是为了让代码编写更简短。利用内存更小。但是,普通情况下非常多程序猿仅仅能做到第一步,而不能充分在内存中发挥代码的复用性。


    例如以下书上样例:

    template<typename T, std::size_t n>//T为数据类型,n为矩阵大小
        class SquareMatrix{
        public:
            ……
            void invert();//求逆运算
        };
        SquareMatrix<double,5> sm1;
        sm1.invert();//调用SquareMatrix<double,5>::invert
        SquareMatrix<double,10> sm2;
        sm2.invert();//调用SquareMatrix<double,10>::invert

    上面的代码会在运行的过程中,详细化两份invert()函数。这两份函数差点儿全然同样,所以对于内存来说是种浪费。假设想要弥补这样的缺点,我们能够用下面对照样例:

    template<typename T>
    class SquareMatrixBase
    {
    public:
        SquareMatrixBase(T* p) : DataPointer(p){}
        void Invert(size_t n){}
    private:
        T* DataPointer;
    };
    
    
    template <typename T, size_t n>
    class SquareMatrix: private SquareMatrixBase<T>
    {
    public:
        SquareMatrix() : SquareMatrixBase(Data)
        {}
        void Invert()
        {
            SquareMatrixBase::Invert(n);
        }
    private:
        T Data[n * n];
    };
    
     SquareMatrix<double,5> sm1;
     sm1.invert();
     SquareMatrix<double,10> sm2;
     sm2.invert();

    当我们再次调用以上语句时,SquareMatrixBase类的实例在内存中仅仅生成一次。由于每次调用都是double 型的SquareMatrixBase。

    然后矩阵数据是用指针訪问,同一种数据不会被拷贝多份,这样也降低了内存利用。

    总之。下面三条非常重要:
    1. Template生成多个classes与多个函数。所以不论什么template代码都不该与某个造成膨胀的template參数产生相依关系。
    2. 因非类型模板參数而造成的代码膨胀,往往能够消除,做法是以函数參数或者class成员变量替换template參数。
    3. 因类型而造成的代码膨胀,也能够降低,做法是让带有全然同样二进制表述的具现类型共享实现码。

  • 相关阅读:
    ubuntu12.04 安装opencv
    VC warning C4786
    su root 后还是不能使用useradd ,useradd 等命令
    C++数组
    C++多维数组
    Centos7 GUI卸载安装gnome
    linux离线安装软件(三)——Centos7以源码编译方式安装两个版本gcc
    yum和源码编译安装nginx
    Linux修改移动硬盘文件类型
    Django部署时STATIC/MEDIA配置
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5109474.html
Copyright © 2020-2023  润新知