在看<<C++ prime>>中遇到了一个问题,看到一半的时候记得书中讲数组做为函数参数时应当提供额外的形参,可以断定数组的开始和结束。
1、数组做为函数参数的三种方法
//额外传递一个数组大小的形参
int func(int a[],size_t n);
//提供一个数组结束的断定符,例如:C风格的字符串字面值用'\0'断定字符串结束
int func(int a[]);//数组a中必须要有断定符
//使用C++标准库的begin和end函数来获取一个指向数组首元素和尾元素之后的指针,类似于迭代器
int func(begin(a),end(a));
2、问题
我们仔细观察最后一种方法,使用begin和end函数的方法,有没有发现什么??
既然begin和end是一个函数,而且他们的形参也是一个数组,但是他们为什么没有提供额外的参数呢?他们是怎么得到指向尾元素后面的指针的?想想我们自己会怎么实现:
我们自己实现时无非是通过首元素的地址加上数组大小得到,可是,begin和end并没有提供数组大小的形参作为参数呀。
上述问题的答案,其实引出了第四种解决方案,查看C++头文件,begin和end定义在iterator头文件中,gcc是定义在bits文件夹下的range_access.h头文件中,下面是截取该头文件的部分内容。
// <range_access.h> -*- C++ -*-
/**
* @brief Return an iterator pointing to the first element of the array.
* @param __arr Array.
*/
template<class _Tp, size_t _Nm>
inline _Tp*
begin(_Tp (&__arr)[_Nm])
{ return __arr; }
/**
* @brief Return an iterator pointing to one past the last element
* of the array.
* @param __arr Array.
*/
template<class _Tp, size_t _Nm>
inline _Tp*
end(_Tp (&__arr)[_Nm])
{ return __arr + _Nm; }
看到上面内容,才想起,书中讲到数组引用作为函数形参时,用函数模板可以实现给函数传递任意大小的数组:
void print (int (&a)[10]);//该函数只能给它传递大小为10的数组作为实参。
int a[10]={0,1,2,3,4,5,6,7,8,9};
print (a);//正确
int b[3]={1,2,3};
print (b);//错误
3、定义函数模板
定义函数模板时不仅可以指定类型参数,还可以指定非类型参数,例如可以如下定义print函数
template < typename T, size_t N>//T是类型参数,N是非类型参数
void print (const T (&a)[N] )
{
for(const auto &item:a)
{
cout<<item<<' ';
}
cout<<endl;
}
//现在
print(a);//正确
print(b);//也都没有问题
来源:oschina
链接:https://my.oschina.net/u/1269142/blog/601657