无我

让内心永远燃烧着伟大的光明的精神之火!
灵活的思考,严谨的实现
豪迈的气魄、顽强的意志和周全的思考

非类型模板形参取数组的维数

      我们知道,用模板的时候可以为他提供两种类型的模板形参:一种是类型模板形参,一种是非类型模板形参。例如如下声明:
template<class T>void foo(T t);   //用的类型模板形参
template<class T,int n>void foo(T t);   //用了类型模板形参,同时还用到了非类型模板形参int

      两者的区别是:对应类型模板形参,编译器会根据实参(对应模板函数)或者用户指定类型来实例化对应的模板函数或类型。而非类型模板形参主要是用来在模板函数调用时指定该形参的值。
      非类型模板形参最常用的是用来自动获取数组的维数。比如,我们给某个函数传递一个数组,并在函数内部打印这个数组的值,如果没有模板,我们的做法就可能是如下这样:
void print(int r[],int N)
{
    
for (int i=0;i<N;++i)
    {
        cout
<<r[i]<<",";
    }
    cout
<<endl;
}
      因为我们需要知道数组的维数,所以必须要求用户传递第二个参数作为维数传入。

      但是,如果是用非类型模板参数,又该如何用呢?
      我们如果给出如下的方案,并不能完全达到我们的目的:
template<class T,int N>
void print(T r[N])
{
    
for (int i=0;i<N;++i)
    {
        cout
<<r[i]<<",";
    }
    cout
<<endl;
}
因为如果这样调用:   
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])
{
    
for (int i=0;i<N;++i)
    {
        cout
<<r[i]<<",";
    }
    cout
<<endl;
}
      我们就可以直接调用: 
print(ss);    //或者print<int>(ss);
      就可以了。这是为什么呢?

      其实原理是很简单的,如果我们直接将数组名传给一个函数,数组将退化为一个指针,所以编译器自然也就无法用指针来推导维数了。但是我们强调传的是引用的话,编译器就明确知道这是一个数组,所以就去推导维数。我们可以给上面的程序加一句打印语句来测试:
template<class T,int N>
void print(T (&r)[N])
{
    cout
<<sizeof(r)<<endl;
    
for (int i=0;i<N;++i)
    
{
        cout
<<r[i]<<",";
    }

    cout
<<endl;
}

template
<class T,int N>
void print1(T r[N])
{
    cout
<<sizeof(r)<<endl;
    
for (int i=0;i<N;++i)
    
{
        cout
<<r[i]<<",";
    }

    cout
<<endl;
}

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

    
return 0;
}
      运行结果如下:
36
1,2,3,4,5,6,7,8,9,
4
1,2,3,4,5,6,7,8,9,

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


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

posted on 2012-11-09 11:41 Tim 阅读(2066) 评论(0)  编辑 收藏 引用 所属分类: C/C++语言


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


<2014年5月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

导航

统计

公告

本博客原创文章,欢迎转载和交流。不过请注明以下信息:
作者:TimWu
邮箱:timfly@yeah.net
来源:www.cppblog.com/Tim
感谢您对我的支持!

留言簿(9)

随笔分类(173)

IT

Life

搜索

积分与排名

最新随笔

最新评论

阅读排行榜