介绍如何使用C/C++模板提高程序可靠性和简化代码的实现。
模板是指作图或设计方案的固定格式。在代码层面上来看,模板是固定格式的代码。我们通过固定格式的代码模板实现不同的代码模型。C语言模板一般为函数模板,而C++除了函数模板外还有类模板。
模板
- 函数模板格式:
template <typename 模板类型1, typename 模板类型2, ...>
返回值类型 函数名字(参数列表...)
{
函数主体
...
}
- 函数模板使用:
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);
- 类模板格式:
template <class 模板类型1, class 模板类型2, ...>
class 类名
{
...
}
- 类模板使用:
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);
不用模板&用模板
我们不使用模板交换两个值的一般实现方法:
/* 交换两个整型值 */
void swap(int &a, int& b)
{
...
}
/* 交换两个浮点值 */
void swap(float &a, float& b)
{
...
}
/* 交换两个字符串 */
void swap(string &a, string& b)
{
...
}
/* 交换两个列表 */
void swap(list &a, list& b)
{
...
}
使用函数模板后,这样会变得非常简单:
/* 实现交换两个数的模板函数 */
template <typename T>
void swap(T &a, T& b)
{
...
}
在使用模板的地方编译器会在编译期展开,自动生成代码。模板也可以看作类型安全的宏。 例如:
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);
}
编译器就会自动生成以下代码:
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);
}
这样我们平时一些重复的代码就可以利用模板特性让编译器自动生成了,从而提高程序可靠性和简化代码的实现。
模板威力
- 使用模板函数来实现编译期计算数组长度(在编译期就能获取到数组长度)。
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 */
- 类模板,实现不同类的单例。
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();
- 利用模板针对性能优化,尽管下列例子在一维数组基本没什么优化,但在用在多维数组上却是可以优化数据的分页缓存刷新,从而提升性能。
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);
更多精彩内容请关注公众号Qt君,第一时间获取推送信息。
网友评论