新网创想网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
数组参数属于指针参数.
创新互联公司一直在为企业提供服务,多年的磨炼,使我们在创意设计,全网整合营销推广到技术研发拥有了开发经验。我们擅长倾听企业需求,挖掘用户对产品需求服务价值,为企业制作有用的创意设计体验。核心团队拥有超过10年以上行业经验,涵盖创意,策化,开发等专业领域,公司涉及领域有基础互联网服务光华机房服务器托管、重庆APP软件开发、手机移动建站、网页设计、网络整合营销。
指针参数即时传址参数(或叫引用参数), 如果想在函数中修改参数的值, 这是唯一的途径.
如果把数组当作参数, 不管你愿意与否, 它就是指针, 指向第一个值的指针.
1. 数组参数就是指向第一个元素的指针: #include stdio.h
void getArr(int p[], int si);
int main(void)
{
int ns[] = {1,2,3,4,5};
getArr(ns, sizeof(ns)/sizeof(ns[0]));
getchar();
return 0;
}
void getArr(int p[], int si) {
int i;
for (i = 0; i si; i++) {
printf("%d\n", p[i]);
}
}
2. 干脆直接声明为指针: #include stdio.h
void getArr(int *p, int si);
int main(void)
{
int ns[] = {1,2,3,4,5};
getArr(ns, sizeof(ns)/sizeof(ns[0]));
getchar();
return 0;
}
void getArr(int *p, int si) {
int i;
for (i = 0; i si; i++) {
printf("%d\n", p[i]);
}
}
3. 即使你在形参中指定维数也不起作用: #include stdio.h
void getArr(int p[2], int si);
int main(void)
{
int ns[] = {1,2,3,4,5};
getArr(ns, sizeof(ns)/sizeof(ns[0]));
getchar();
return 0;
}
void getArr(int p[2], int si) {
int i;
for (i = 0; i si; i++) {
printf("%d\n", p[i]);
}
}
4. 既然是指针, 其值就有被修改的可能: #include stdio.h
void getArr(int p[], int si);
int main(void)
{
int ns[] = {1,2,3,4,5};
size_t i;
getArr(ns, sizeof(ns)/sizeof(ns[0]));
for (i = 0; i sizeof(ns)/sizeof(ns[0]); i++) {
printf("%d\n", *(ns+i));
}
getchar();
return 0;
}
void getArr(int p[], int si) {
int i;
for (i = 0; i si; i++) {
p[i]++;
}
}
5. 如果是字符数组, 它自己能判断数组尾界: #include stdio.h
void getArr(char p[]);
int main(void)
{
char ns[] = "ABCDEFG";
getArr(ns);
getchar();
return 0;
}
void getArr(char p[]) {
int i;
for (i = 0; p[i]; i++) {
printf("%c: %d\n", p[i], p[i]);
}
}
其实无非两种,一种是具体化(又叫偏特化)一种是实例化(又叫全特话),对于具体化,就是
对模板的范围进一步压缩,并给这个更小的范围从新定义类成员(包括数据成员和方法)。对于实例化就是直接生成模板中某种实例(注意:同时给一个模板生成同一个实例化和具体化将报错)。举例:
#includeiostream
#includecstdio
#includestdlib.h
using namespace std;
template typename T1,typename T2//#1
class A
{
int a;
public:
A (){cout"this is AT1,T2 default constructor function!\n";}
};
template typename T1
class AT1,int//部分的具体化 #2
{
int b;
public:
A (){cout"this is AT1,int default constructor function!\n";}
};
template class Aint,char;//显示的实例化,将直接生成该类型类定义
int main()
{
class Aint ,int a;//隐式实例化 ,将隐式生成#2 的实例
class Aint ,char b; //隐式实例化,将隐式生成#1的实例
return 0;
}
我认为1不是实例化,而是函数模板的定义。所谓的实例化是指在编译或链接时生成函数模板或类模板的具体实例源代码。也就是通过函数模板生成模板函数的过程。
2应该是显式实例化,该行为发生在在编译链接后,函数调用前(隐式(implicit)实例化发生在函数调用后)。
3是显式具体化,这玩意的作用就一个:给特定的类型定义特定的操作。比如在你给的例子中,swap()只能被int型的模板函数调用,其他类型没这个操作。
函数void swap(int, int)只能被接受int型变量为参数,而模板函数可以接受任意类型变量为参数。
templateclass A
void fun(A a){}
template
void funint(int a){/*....*/}//显式具体化
void main()
{
float a=0;
funfloat(a);//显式实例化
}
模板在需要的时候才会实例化
各种用
C
语言实现的模板可能在使用形式上有所不同。现以一个求和函数
Sum
为例,用
C++
Template
可写如下:
template
R
Sum(const
T
*array,
int
n)
{
R
sum
=
0;
for
(int
i
=
;
i
n
;
++i)
sum
+=
i;
return
sum;
}
如果不是内置类型,该模板隐式地需要
有R
R::operator+=(T)运算符可用。
1.
使用函数指针作为
Functor
替换者
Typedef
struct
tagAddClass
{
Void
(*add)(char*
r1,
const
char*
r2);
Int
elemSize;
Char
sum[MAX_ELEM_SIZE];
}
AddClass;
void
Sum(AddClass*
self,
const
char*
array,
int
n)
{
for
(int
i
=
;
i
n
;
++i)
self-add(self-sum,
array
+
i*self-elemSize);
}
使用时:
Void
AddInt(char*
r1,
const
char*
r2)
{
*(long*)r1
+=
*(int*)r2;
}
AddClass
addClass
=
{AddInt,
2,
};
Int
array[100];
Read(array);
Sum(addClass,
array,
100);
…..
2.
用宏作为Functor的替换者
#define
GenSumFun(SumFunName,
Add,
RetType,
ElemType)
RetType
SumFunName
(const
ElemType
*array,
int
n)
\
{
RetType
sum
=
0;
for
(int
i
=
;
i
n
;
++i)
Add(sum,
i);
return
sum;
}
使用时:
#define
AddInt(x,
y)
((x)
+=
(y))
GenSumFun(SumInt,
AddInt,
long,
int)
…..
Int
array[100];
Read(array);
Long
sum
=
SumInt(array,
100);
…..
3.
所有可替换参数均为宏
至少需要一个额外的文件(实现文件)为
impsum.c
/*
impsum.c
*/
RetType
FunName(const
ElemType
*array,
int
n)
{
RetType
sum
=
0;
for
(int
i
=
;
i
n
;
++i)
Add(sum,
i);
return
sum;
}
使用时:
#undef
RetType
#undef
FunName
#undef
ElemType
#undef
Add
#define
AddInt(x,
y)
((x)
+=
(y))
#define
RetType
long
#define
FunName
SumInt
#define
ElemType
int
#define
Add
AddInt
#include
impsum.c
…..
Int
array[100];
Read(array);
Long
sum
=
SumInt(array,
100);
4.
总结:
第一种方法,易于跟踪调试,但是效率低下,适用于对可变函数(函数指针)的效率要求不高,但程序出错的可能性较大(复杂),模板函数(Sum)本身很复杂,模板参数也比较复杂(add)的场合。
第二种方法,效率高,但很难跟踪调试,在模板函数和模板参数本身都很复杂的时候更是如此。
第三种方法,是我最近几天才想出的,我认为是最好的,在模板参数(Add)比较复杂时可以用函数(第二种也可以如此),简单时可以用宏,并且,易于调试。在模板函数本身很复杂,而模板参数比较简单时更为优越。但是,可能有点繁琐。
明确实例化点。例如
template typename T
void f(T t) {
g(t);
}
class A{};
void g(const A a); // 函数1
template void f(A t); // 显式实例化
void g(A a) { // 函数2
f(a); // 调用函数1,因为显式实例化时函数2 还没有声明
// 如果没有显式实例化则调用函数2,即无穷递归
}