前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C/C++黑魔法-模板威力

C/C++黑魔法-模板威力

作者头像
Qt君
发布2019-12-25 11:14:46
5540
发布2019-12-25 11:14:46
举报
文章被收录于专栏:跟Qt君学编程跟Qt君学编程

介绍如何使用C/C++模板提高程序可靠性和简化代码的实现。

  模板是指作图或设计方案的固定格式。在代码层面上来看,模板是固定格式的代码。我们通过固定格式的代码模板实现不同的代码模型。C语言模板一般为函数模板,而C++除了函数模板外还有类模板

模板

  • 函数模板格式:
代码语言:javascript
复制
template <typename 模板类型1, typename 模板类型2, ...>
返回值类型 函数名字(参数列表...)
{
	函数主体
	...
}
  • 函数模板使用:
代码语言:javascript
复制
template <typename T>
void swap(T &a, T& b) 
{
	T temp = a;
	a = b;
	b = temp;
}

/* 使用 */
int a = 1;
int b = 2;
swap<int>(a, b);
  • 类模板格式:
代码语言:javascript
复制
template <class 模板类型1, class 模板类型2, ...>
class 类名
{
	...
}
  • 类模板使用:
代码语言:javascript
复制
template<class T>
class List
{
public:
    const T &at(int i) const
    {
        return m_list.at(i);
    }

    void append(const T &t)
    {
        m_list.push_back(t);
    }

private:
    vector<T> m_list;
};

/* 使用 */
List<string> stringList;
stringList.append("Hello world");
cout << stringList.at(0);

不用模板&用模板

  我们不使用模板交换两个值的一般实现方法

代码语言:javascript
复制
/* 交换两个整型值 */
void swap(int &a, int& b) 
{
    ...
}

/* 交换两个浮点值 */
void swap(float &a, float& b) 
{
   ...
}

/* 交换两个字符串 */
void swap(string &a, string& b) 
{
    ...
}

/* 交换两个列表 */
void swap(list &a, list& b) 
{
    ...
}

  使用函数模板后,这样会变得非常简单:

代码语言:javascript
复制
/* 实现交换两个数的模板函数 */
template <typename T>
void swap(T &a, T& b) 
{
   ...
}

在使用模板的地方编译器会在编译期展开,自动生成代码。模板也可以看作类型安全的宏。 例如:

代码语言:javascript
复制
template <typename T>
void swap(T &a, T& b) 
{
   ...
}

int main(int argc, char *argv[])
{
    int a = 1;
    int b = 2;
    float c = 0.1;
    float d = 0.2;
    swap<int>(a, b);
    swap<float>(c, d);
}

  编译器就会自动生成以下代码:

代码语言:javascript
复制
void swap(int &a, int& b) 
{
    ...
}

void swap(float &a, float& b) 
{
   ...
}

int main(int argc, char *argv[])
{
    int a = 1;
    int b = 2;
    float c = 0.1;
    float d = 0.2;
    swap(a, b);
    swap(c, d);
}

这样我们平时一些重复的代码就可以利用模板特性让编译器自动生成了,从而提高程序可靠性和简化代码的实现。

模板威力

  1. 使用模板函数来实现编译期计算数组长度(在编译期就能获取到数组长度)。
代码语言:javascript
复制
template <typename T, size_t N>
inline size_t GetArrayLength(const T(&)[N])
{
    return N;
}

/* 使用 */
int array[] = {0, 1, 2, 3, 4, 5};
cout << GetArrayLength<int>(array) << endl;
cout << GetArrayLength(array) << endl; /* 可省略类型,让编译器自动推导。*/
/* 输出: 6 */
  1. 类模板,实现不同类的单例。
代码语言:javascript
复制
template<typename T>
class Singleton
{
public:
    inline static T& getInstance()
    {
        static T _instance;
        return _instance;
    }

private:
    Singleton();
    Singleton(Singleton const&);
    ~Singleton();

    Singleton& operator= (Singleton const&);
};

/* 使用 */
string str = Singleton<string>::getInstance();
  1. 利用模板针对性能优化,尽管下列例子在一维数组基本没什么优化,但在用在多维数组上却是可以优化数据的分页缓存刷新,从而提升性能。
代码语言:javascript
复制
template<typename T, int N>
class Copy
{
public:
     static inline void exec(T *in, T *out)
     {
         Copy<T, N - 1>::exec(in, out);
         out[N - 1] = in[N - 1];
     }
};

template<typename T>
class Copy<T, 0> /* 特化, 这里用于结束递归 */
{
public:
      static inline void exec(T *in, T *out) { }
};

template<typename T, int N>
void copy(T (&in)[N], T (&out)[N])
{
    Copy<T, N>::exec(in, out);
}

/* 使用 */
int in[5] = {1, 2, 3, 4, 5};
int out[5] = {0};
copy(in, out);
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Qt君 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 模板
  • 不用模板&用模板
  • 模板威力
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档