波奇学C++:缺省参数,函数重载,引用

目录

缺省函数:给定函数参数有默认值

函数重载:函数可以接收不同类型的函数

引用:对指针的优化

关键字auto:类型指示符,自动推导数据类型

内联函数:对宏函数优化,在函数前加入inline。


缺省函数:给定函数参数有默认值

int add(int a,int b=1)
{
    return a+b;
}
int main()
{
    printf("%d",add(2));
    return 0;
}
3

如图,我们给有两个参数的函数只传了一个参数,依然可以运行起来原因是c++支持默认参数,和python一样,但没有python这么智能。表现在以下方面

缺省参数的限制

1.当有多个参数时,从左往右

add(2,3)//a=2,b=3

2.不能指定传参,python可以指定传参

add(a=1,b=2);//报错

3.声明给缺省参数,定义不用给

int add(int a,int b=1);
int add(int a,int b)
{
    return a+b;
}

或者我们可以简单理解为函数调用先找声明,声明把缺省值传给函数定义

函数重载:函数可以接收不同类型的函数

int add(int a,int b)
{
    return a+b;
}
float add(float a,float b)
{
    return a+b;
}
add(1,2);//3
add(1.0,2.0);//3

为什么会c++支持函数重载?

代码编译以下流程:编译->汇编->链接

c和c++在汇编时产生符号表(简单理解为函数名以及函数地址),方便机器找到函数调用。

c++函数名被修饰,生成一个含有参数含义信息的函数名,因此机器可以通过参数信息找到对应的重名函数,精准调用,本质上两个不同的函数拥有同样的名字而已,而c没有修饰规则,所以只能有一个函数。

函数修饰规则能加入返回值信息吗?

目前不可以,因为在函数调用前,不知道函数的返回值信息,除非,已知函数返回值才能调用函数的规则。

python函数调自动识别参数类型,由此可推断有可能当一个函数被用户创建时,python可能产生复制很多个不同类型参数的函数。

引用:对指针的优化

void swap1(int*pa,int*pb)
{
    int cmp=*a;
    *a=*b;
    *b=cmp;
}
void swap2(int&a,int&b)
{
    int cmp=a;
    a=b;
    b=cmp;
}
int main()
{
    int a=0;
    int b=1;
    int& c=a;
    c=b;
    swap(&a,&b);
    swap2(a,b);
    return 0;
}

图中c和a指向同一个空间,把c看成a的别名,类别python中列表名给另外变量,两个变量名都指向同一列表。

有以下规则:1.引用不能为空,并且只能引用不能改指向,一个变量却能有多个引用

 c=b;//把b的值赋给c,相当于改变了a的值,但是c引用指向依然是a
int& d = a//c和d都是a的引用

2.引用的类型是&前的类型。

int a=0
int*p=&a;
int*&c=p;//c的类型是int*

3.引用没用开新的空间。

4.引用的用法:

 1.引用作输出型参数

什么是输出型参数?在函数中修改影响到函数外的值,如指针,输入型参数,只能访问使用,可以加const。

如上面的swap2:不妨理解成,它直接直接把形参变成实参使用(感觉更像先拿指针再解引用后使用?),这可以使得调用指针传参时,实参形式保持一致。

优势:引用可以提高效率,对于大对象,深拷贝对象。

2.引用作返回值:优化静态区变量,堆上的变量返回时创建临时变量问题

int& Count1()
{
	static int n = 0;//
	n++;
	return n;
}//返回n的别名
int Count2()
{
	static int n = 0;//
	n++;
	return n;
}//返回n的值
int a=Count1()//相当于拷贝
int& b=Count1()//别名赋给别名,相当于创建新的别名

在Count2中 n不会直接返回,会生成临时变量,放在寄存器中,再给a。(是否会生成临时变量取决于函数的返回值类型,这个机制适合函数栈帧的变量,函数栈帧内的变量会销毁,必须用临时变量保存,对于堆或者静态区变量,无疑是没有必要的。)

引用做返回值,对于堆或静态区变量,不生成临时变量,减少拷贝,尤其是大对象,深拷贝对象会提交效率。

引用作返回值,用引用接收时,可以直接修改函数内部的变量

常引用问题:const

权限问题:int 的权限>const int 因为const修饰后由读写变成了只读模式。引用时可以权限平移,权限缩小,但不能放大。

如图 int& 类型引用了const int 类型放大了权限,下面却可行,因为,相当于拷贝。

const int a = 1;
int&b =a;//报错,引用过程中权限不能放大


const int c=0;
int d =c
//可以,相当于拷贝,d的修改不影响c

如图权限的平移和缩小,其中z不能改变,x却可以改变,应为const 只修饰c,只有c是只读模式。

int x=0;
int& y=x;
const int& z =x;
x++;//x = 1
z++;//错误,z 被const修改,不能通过修改x
//此处只缩小的z的权限,对x无影响

const 修饰的引用可以对常量引用,会开辟临时空间

const int& a =10//对常量取别名,会开辟空间,必须用加上const才能引用常量

类型转化和函数返回时(返回值类型不是引用)会有临时变量,dd->临时变量->ii,临时变量具有常性

double dd =1.11;
int ii=dd;
const int& rii=dd;//成功
int &dii = dd//报错

int fun()
{
    static int ii =1;
    return ii;
}
int &rii =fun();//报错

引用的语法层面上时不开空间的,从汇编语言的角度和指针一样,是开空间的。

引用会比指针更安全。

关键字auto:类型指示符,自动推导数据类型

int a =0;
auto b =a;
//自动推导b的值为auto

auto声明指针类型时 auto和auto*没有区别,auto声明引用类型时必须加上&

auto a=&x;
auto* b=&x;
auto& c=x;

auto不能作参数类型

int add(auto x, auto y)
{
 return x+y;
}

auto用法

int arr[]={1,2,3,4,5};
//依次取数组中的数据赋值给e,自动迭代,自动判断介绍
for(int e:arr)
{
    cout<<e<<endl;
}
for(auto e:arr)
{
    cout<<e<<endl;
}
int arr[]={1,2,3,4,5};
//修改e值
for(auto& e:arr)
{
    cout<<e<<endl;
}

在C++中,定义了NULL 为0,为了解决空指针问题,把nulllptr 宏定义为((void*)0),C++编译器允许函数参数没有变量名。
 

内联函数:对宏函数优化,在函数前加入inline。

 问题引入:当我们多次频繁调用某一函数时,可能加大栈帧开销。

C语言的解决方案:宏函数:不用建立栈帧,提高效率,不能调试,可能出错。

C++优化方案:

inline int  Add(int x,int y)
{

    return (x+y)*10;
}

内联函数同样不用建立函数栈帧(汇编代码下没有调用函数的call指令,而是变成汇编指令),而且可以调试,但只适用于简单函数,复杂内联函数太多会造成代码膨胀,进而可执行程序变大。

对于编译器而言,内联往往只是建议,实际情况由编译器决定。默认debug下,不会有内联

内联函数声明定义不建议分开,内联函数会展开,不会出现在符号表上,如果分开那就找不到定义了。换句话说,内联函数定义声明都在类中。

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值