C++模版初探之模版函数

第一次阅读有关C++模版方面的内容,做个记录

模版属于泛函编程。所谓泛函,就是以独立于任何特定的类型的方式编写代码。

下面是一个简单的函数模版的例子,用来比较两个数的大小。

#include <iostream>
using namespace std;

template <typename T>
T compare(T a, T b)
{
	return a > b ? a : b;
}

int main()
{
	int a = 4, b = 5;
	cout << compare(a, b) << endl;
	double c = 3.1, d = 8.7;
	cout << compare(c, d) << endl;
	return 0;
}

其中的4-8行是一个 函数模版,以关键字template开始,后面尖括号中是模版形参表,其中是一个或多个 模版形参的列表。

模版形参分为两类:类型形参和非类型形参。

类型形参跟在关键字typename或者class后面,这里这两个关键字没有太大区别。定义好的类型形参和普通类型一样在函数中使用。

非类型形参主要是用来在模板函数调用时指定该形参的值。

非类型形参最常见的用途是取数组的维数:

比如,我们给某个函数传递一个数组,如果没有模板,我们的做法就可能是如下这样:

void print(int r[],int N)
{
	...;
}
因为我们需要知道数组的维数,所以必须要求用户传递第二个参数作为维数传入。

但是,如果是用非类型模板参数,又该如何用呢?

我们如果给出如下的方案,并不能完全达到我们的目的: 

template<class T,int N>
void print(T r[N])
{
	...;
}

因为如果这样调用:   

int main()
{    
    int ss[] = {1,2,3,4,5,6,7,8,9};
    print(ss);   //或者print<int>(ss);
    return 0;
}

编译器会抱怨说:“void print(T [N])”: 未能从“int [9]”为“int [N]”推导 模板 参数”。也就是我们还是得指定N:print<int,9>(ss)才行。如果是这样,那岂不还不如将维数放到函数的参数里面了。是不是?

其实,这完全不能怪编译器或者模板,因为只要这样写就完全可以了:

template<class T,int N>
void print(T (&r)[N])
{
    ...;
}

我们就可以直接调用,为什么呢?

 其实原理是很简单的,如果我们直接将数组名传给一个函数,数组将退化为一个指针,所以编译器自然也就无法用指针来推导维数了。但是我们强调传的是引用的话,编译器就明确知道这是一个数组,所以就去推导维数。我们可以给上面的程序加一句打印语句来测试:

template<class T,int N>
void print(T (&r)[N])
{
    cout<<sizeof(r)<<endl;
}
template<class T,int N>
void print1(T r[N])
{
    cout<<sizeof(r)<<endl;
}
int main()
{    
    int ss[] = {1,2,3,4,5,6,7,8,9};
    print(ss);    
    print1<int,9>(ss);    
    return 0;
}

很明显可以看出,传引用的方式他知道是一个数组,所以sizeof是按数组的方式计算的4*9=36.而第二种方式尽管我告诉他维数了,并且打印出结果了,但是丝毫没有改变编译器将print1的参数T r[N]视为一个指针的事实,所以sizeof的值为4.

好了,总结一下就是:如果希望用非类型模板形参的方式取数组的维数时,请记住用数组引用的方式作为形参!


非类型形参部分,引用了如下地址的博客:

http://www.cppblog.com/Tim/archive/2012/11/09/194965.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值