函数探幽.docx

上传人:b****8 文档编号:8991285 上传时间:2023-02-02 格式:DOCX 页数:13 大小:3MB
下载 相关 举报
函数探幽.docx_第1页
第1页 / 共13页
函数探幽.docx_第2页
第2页 / 共13页
函数探幽.docx_第3页
第3页 / 共13页
函数探幽.docx_第4页
第4页 / 共13页
函数探幽.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

函数探幽.docx

《函数探幽.docx》由会员分享,可在线阅读,更多相关《函数探幽.docx(13页珍藏版)》请在冰豆网上搜索。

函数探幽.docx

函数探幽

第八章函数探幽

记住:

arr[i]==*(arr+i)&arr[i]==arr+i

8.1内联函数(inline)(使用范围:

执行代码较短)

使用方法:

●在函数声明前加上inline

●在函数定义前加inline

内联与宏

内联函数是通关过传递参数来实现的,宏(#define)是通过文本替换来实现的。

注意:

如果使用C语言的宏执行了类似函数的功能,应考虑将他们转换为C++内联函数。

8.2引用变量

8.2.1创建引用变量

Intrats;

Int&rodents=rats;rodents是rats的引用(他们指向相同的值和相同的内存单元)

Int*prats=&rats;创建指向rats的指针

引用与指针的差别

Ø声明引用时将其初始化,不能像指针先声明在赋值。

(通过初始化声明来设置引用,不能通过赋值来设置)

Ø引用更加接近于const指针,int&rodents=rats;int*constpr=&rats;

8.2.2将引用作为函数参数(按值传递/按引用传递)

Voidsneezy(int*p);

Intmain()

{

Inttimes=20;

Sneezy(×);

}

Voidsneezy(int*p)

{

}

注;swap(int&a,int&b)//inttemp;temp=a;a=b;b=temp;

Swap(int*a,int*b);//inttemp;temp=*a;*a=*b;*b=temp;

Swap(inta,intb);//inttemp;temp=a;a=b;b=temp;失败,复制的副本

临时变量、引用参数和const

有名称和类型的数据对象,才可以为其创建引用,而不需要临时变量。

(参数必须是const引用)

实际上,对于形参为const引用的C++函数,如果实参不匹配,其行为类似于按值传递。

应该尽可能的使用const引用

右值引用(C++11):

引用后面可以是字面常量或者多项式表达式

Double&&rref=std:

:

sqrt(36.0);

Doublej=15;

Double&&jref=2.0*j+18.5;

Std:

:

cout<

Std:

:

cout<

8.2.3引用用于结构(提高传递效率)

Doublem=sqrt(16.0);4.0被存放在临时位置,然后复制给m。

Dup=accumulate(team,five);accumulate()返回的是引用,team值会直接复制给Dup。

注意:

避免返回函数终止时,不在存在的内存单元的引用(临时变量的引用)。

解决办法:

返回一个作为参数传递给函数的引用。

另外一种方法,使用new为字符串分配内存空间,并返回指向该内存空间的指针。

将const用于引用返回类型:

8.2.4将引用用于类对象(类对象传递给函数时,C++通常做法就是引用)

注意:

不可以返回临时变量的引用。

比如:

(1)Conststring&vision3(string&s1,conststring&s2)

{

Stringtemp;

Temp=s2+s1+s2;

Returntemp;错误返回的是临时变量的引用

}

Result=version3(input,”***”);程序试图引用已经释放的内存。

(2)const引用类型的形参,假如实参类型与引用的参数类型不匹配,但可以转换为引用类型,程序会创建正确类型的临时变量,使用转换后的实参值来初始化它,然后传递一个指向该临时变量的引用。

8.2.5对象、继承与引用

使得能够将特性从一个类传递到另一个类的语言特性被称为继承(第13章讨论)

如:

ØOstream基类Ofstream派生类派生类继承了基类的方法。

Ø基类的引用可以指向派生类的对象,而无需强制类型转换。

何时使用引用参数

8.3默认参数

对于带参数列表的函数,必须从右向左添加默认值,也就是说要为某个参数设置默认值,则必须为它右边所有的参数提供默认值。

功能:

能够使用不同数目的参数调用同一个函数。

Intharpo(intn,intm=4,intj=5);valid

Intchico(intn,intm=6,intj);invalid

Intgroucho(intk=1,intm=2,intn=3);valid

Beeps=harpo(3,,8);错误,不可以跳过任何参数。

8.4函数重载(函数多态:

使用多个同名的函数)

C++允许定义名称相同的函数,条件是特征标不同(参数数目或者参数类型不同)

注:

ØC++编译器将类型引用与类型本身看成同一个特征标。

Ø匹配函数时,const变量与非const变量,需要注意非const变量赋值给const变量是合法的,反之非法。

Ø特征标进行函数重载,不是函数类型。

Ø类型重复的话,寻找最匹配原型。

Tips:

取一个整数的前几位与取一个字符串的前几位代码对比:

Unsignedlongleft(unsignedlongnum,unsignedct)

{

Unsigneddigits=1;

Unsignedlongn=num;

If(ct==0||num==0)return0;

While(n/=10)digits++;

If(digits>ct)

{

Ct=digits-ct;

While(ct--)

Num/=10;

Returnnum;

}

Else

Returnnum

}

Char*left(constchar*str,intn)

{

if(n<0)n=0;

Char*p=newchar[n+1];

Inti;

For(i=0;i

P[i]=str[i];

While(i<=n)

P[i++]=‘\0’;

Returnp;

}

8.5函数模板(对不同类型使用同一种算法的时候,可以使用模板)

Templatetypename可以换成class;

Voidswap(anytype&a,anytype&b)

{

Anytypetemp;

Temp=a;

A=b;

B=temp;

}

重载的模板(模板的特征标不同)

template

voidswap(T&a,T&b);

template

voidswap(T*a,T*b,intn);

模板的局限性:

编写的模板函数无法处理某些类型。

●运算符重载,用于特定的结构或者类(第11章)

●为特定类型提供具体化的模板定义(本章介绍这种解决方案)

8.5.1显示具体化(编译器找到与函数调用匹配的具体化定义时,将使用该定义而不再寻找模板)

对于给定的函数名,可以有非模板函数、模板函数和显示具体化模板函数以及重载版本。

优先级:

非模板函数>=具体化函数>=常规模板

Template

Voidswap(T&,T&);

Voidswap(job&,job&);

Template<>voidswap(job&,job&)显示具体化模板函数

Template<>voidswap(job&,job&)简化版本

Templatevoidswap(char&,char&)显示实例化模板函数

8.5.2实例化和具体化(注意区别:

显示实例化和具体化)

函数模板本身不是函数定义,编译器在使用特定类型的函数模板时候,才会生成函数定义,得到的是模板的实例。

称为隐式实例化。

C++允许显示实例化:

swap();

声明:

Templatevoidswap(int,int);

显示具体化的函数声明为:

(不需要通过函数模板来生成还是定义,而应该使用专门为int类型显示的函数定义)

Template<>voidswap(int&,int&);

Template<>voidswap(int&,int&);

隐式实例化、显示实例化、显示具体化统称为具体化。

8.5.3编译器使用哪个函数版本

确定哪个函数更好的时候,从最佳到最差的顺序如下所述:

详细见第三章:

char到float转换属于标准转换。

当出现两个函数均完全匹配的时候就会出现错误,这一规则有两个例外:

1完全匹配和最佳匹配

注:

type(argument-list)意味着用作实参的函数名与用作形参的函数指针只要类型和参数列表相同,就是匹配的。

问题:

这边究竟模板1具体还是模板2具体?

(这边解释感觉前后矛盾)分析的结果感觉应该是模板2。

2部分排序规则示例(总结)

3.创建自定义选择

8.5.4模板函数的发展(C++98到C++11)

C++11中的关键字decltype用这个关键字来推算出类型。

Template

Voidft(T1x,T2y)

{

Decltype(x+y)xpy=x+y;

}

Decltype比这些实例演示要复杂一些。

为确定类型,编译器必须遍历一个核对表,简化版如下:

●如果expression是一个没有用括号括起的标识符。

则var的类型与该标识符类型相同。

doublex=5.5;double&rx=x;decltype(x)w;(w类型为double)decltype(rx)y;(y的类型为double&)

●如果expression是一个函数的调用,则var的类型与函数的返回类型相同。

Longindeed(int);decltype(indeed(3))m;(m的类型为int)

●如果expression是左值则var为指向其类型的引用。

(用括号括起来的标识符)doublexx=4.4;decltype((xx))r2=xx;(double&)decltype(xx)w=xx;(double)

●如果上述类型全都不满足则var类型与expression的类型相同。

intj=3;

decltype(j+6)i1;i1是int类型

另外一种函数声明语法(C++后置返回类型)

Doubleh(intx,floaty);

Autoh(intx,floaty)->double;被称为后置返回类型

(auto与decltype结合起来)

Template

Autogt(T1x,T2y)->decltype(x+y)

{

…..

Returnx+y;

}

Template

Voidft(T1x,T2y>

{

?

type?

xpy=x+y;

}

注:

可以将?

type?

换为decltype(x+y)

x,y均有作用域,可以使用decltype

Template

?

type?

ft(T1x,T2y>

{

return=x+y;

}

注:

不可以将?

type?

换为decltype(x+y)

x,y不在作用域内,不可以使用decltype,应该将auto与decltype结合起来。

如上面所示

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1