C++模板

C++模板,第1张

模板入门
    • 什么时候使用模板
    • 如何创建模板
    • 当实例化模板时会发生什么?
    • 当使用相同类型实例化模板多次时,会发生什么?
      • 延迟实例化

模板(类模板或函数模板)和类或函数很相似。


当你实例化一个模板,你就创建了一个具体的类或函数。


出于习惯,有时也将类模板称为泛型类,将函数模板成为泛型函数。



为了可视化模板实例化的过程,可以使用C++ Insights。


什么时候使用模板

你应该使用模板当函数或类代表了一个抽象的概念,并且不局限于某个特定的类型。


例如:函数max,容器vector都能用于多种类型。


如何创建模板

假如有如下函数:

int max(int lhs, int rhs) {
    return (lhs > rhs)? lhs : rhs;
}

将其变为一个模板很简单:

  1. 在函数前面加上template
  2. 使用参数T替换具体的类型int。


template    // typename 也可以使用 class 代替
T max(T lhs, T rhs) {   
    return (lhs > rhs)? lhs : rhs;
}
当实例化模板时会发生什么?

使用intdouble实例化函数模板max:

template 
T max(T lhs, T rhs) {
    return (lhs > rhs)? lhs : rhs;
}

int main() {
    max(10, 5);
    max(10.5, 5.5);
}

C++ Insights显示了模板实例化的具体过程:

template 
T max(T lhs, T rhs) {
    return (lhs > rhs)? lhs : rhs;
}

/* First instantiated from: insights.cpp:8 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
int max(int lhs, int rhs)
{
  return (lhs > rhs) ? lhs : rhs;
}
#endif


/* First instantiated from: insights.cpp:9 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
double max(double lhs, double rhs)
{
  return (lhs > rhs) ? lhs : rhs;
}
#endif


int main()
{
  max(10, 5);
  max(10.5, 5.5);
  return 0;
}

可以看到编译器分别为intdouble生成了特化的函数。


当使用相同类型实例化模板多次时,会发生什么?

下面是一个类模板的例子。


template 
class Array{
 public:
    int getSize() const{
        return N;
    }
 private:
    T elem[N];
};

int main() {
  
    Array myArr1;  // (1)
    Array myArr2; // (2)
    Array myArr3;  // (3)
  
}

Array实例化了2次,Array (line 2)实例化了一次。


C++ Insights的主要输出如下:

template 
class Array{
 public:
    int getSize() const{
        return N;
    }
 private:
    T elem[N];
};

/* First instantiated from: insights.cpp:13 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class Array
{
  
  public: 
  inline int getSize() const;
  
  
  private: 
  int elem[5];
  public: 
  // inline Array() noexcept = default;
};

#endif


/* First instantiated from: insights.cpp:14 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class Array
{
  
  public: 
  inline int getSize() const;
  
  
  private: 
  int elem[10];
  public: 
  // inline Array() noexcept = default;
};

#endif

可以看到,第二次实例化(3)Array使用了第一次实例化的代码。



有2个有趣的发现:1. 模板实例化是延迟(lazy)的; 2. 可以使用非类型作为模板参数。


延迟实例化

从上面输出可以看到成员函数getSize()没有实例化,仅有声明。


这个意味着如果没有使用将不会被实例化。



修改代码如下:

int main() {
  
    Array myArr1;  
    Array myArr2; 
    Array myArr3;  
    myArr3.getSize();     // (1)
  
}

编译器将会生成getSize的代码:

...
/* First instantiated from: insights.cpp:13 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class Array
{
  
  public: 
  inline int getSize() const
  {
    return 5;
  }
  
  
  private: 
  int elem[5];
  public: 
  // inline Array() noexcept = default;
};

#endif
...

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/562717.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-02
下一篇 2022-04-02

发表评论

登录后才能评论

评论列表(0条)

保存