[C++潜心修炼] 小试牛刀
Posted 一个正直的男孩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C++潜心修炼] 小试牛刀相关的知识,希望对你有一定的参考价值。
打怪打怪打怪……………………
文章目录
缺省参数
你是否有这样的烦恼,传参的时候少传参数甚至没传参数这种粗心问题烦恼,没事让函数缺省参数拯救你,只要不忘记写缺省参数
缺省参数:你可以在声明函数的时候给形参定义,你没有有传参的时候会自动补上
代码:
int add(int x=1,int y =2)
{
return x+y;
}
int main ()
{
cout<<add();//不传参数就为3
}
但是有时候记性可能稍微好点,传了几个,或者全部都传了
代码:
int add(int x=1,int y =2,int z=20)
{
return x+y;
}
int main ()
{
cout<<add(4,5,6);//这样传可以
cout<<add(4);//这样也可以
}
总有人会想玩点高操作,你看我我就想给 x ,z 传值怎么说
代码:
int add(int x=1,int y =2,int z=20)
{
return x+y;
}
int main ()
{
cout<<add(4, ,6);
}
显然是不行,因为这涉及一个逻辑问题,你看编译去觉得是传了空呢?还是没有传呢?这个空的话这个6是给 y 还是z
正确与错误的示范
总之缺省参数,就是你最后的一层保障就如家一样,给你十足的安全感,传参要依次给,函数定义缺省参数一定要给全
指针空值nullptr
NULL我的那么完美又那么老实你为啥要找人换我,我要做生产线上的螺丝钉
真的吗,NULL在定义的时候为有俩种情况,为0或者无类型指针(void*)的0
宏定义:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)//把0强制类型转换为void*,
#endif #endif
NULL可能是一个没有引爆器的核弹,一般情况下没事但是存在安全隐患整不定哪天就……
void f(int)
{
cout<<"f(int)"<<endl;
}
void f(int*)
{
cout<<"f(int*)"<<endl;
}
int main()
{
f(0);//"f(int)"
f(NULL); //"f(int)"
f((int*)NULL);//"f(int*)"
return 0;
}
你看这不就炸了吗,虽然有点挑刺,但是被发现了就是问题,我本来传NULL给我的结果是区调用 void f(int*)
(函数重载,简单来说他同名的函数会根据参数调用相对应的函数接口)
为了严谨C++就推出了nullptr,他就代表是空指针常量(nullptr==(void *)0) ,给你放心的保障。
引用
不知道大家有没有看过火影忍者,里面主角鸣人,他的招牌忍术叫多重影分身之术
其中一幕让我印象深刻,他没有朋友,所以用忍术搞了三个分身并给他取了名字…………
不追忆了,进入正题,引用就是给变量取别名,他和变量共用一块空间
的,这个就和联合体很像。他是是C++中指针的进阶版
用法
类型 +&+变量名+实体
代码:
int a =10;
int & a2 = a;//a2是a的别名
类型 + & + 变量名 = 实体
这里要注意了,&在类型后面代表引用,在变量前则取地址
引用的一些性质:
- 你可以给一个变量无限次的取别名,只要你不累就和鸣人一样 (查吨拉)
代码
int a=10;
int &a1=a;
int &a2=a;
int &a3=a;
…………………………
运行结果:
- 一旦你已经是变量的别名,你就不能成为别人的别名
不知道大家有没有去超市买过哪种促销的酸奶,因为快要过期了所以他们为了处理掉会俩三个捆扎在一起销售,看了看自己的一块腹肌哎,这里一旦是别人的别名你就会永久和和他捆绑在一起
int a=10;
int b=20;
int &a1=a;
a1=b;
aout<<a;//输出是啥?
这儿其实是赋值了,引用的概念是共用一块空间的哟,那么改变a1那a也被改了
上面除了不开空间以外指针似乎也可以完成,那么他真正用处是啥?
真正的用处
- 做参数
很多书上都是怎么说的,函数传参的时候建议传值,为什么呢??? 因为行参是实参的一份临时拷贝 (就是你原来数据是多大他会开一块一样大的空间存储数据),为了节省空间
和提高运行效率
建议传指
代码:
int Swap(int a[],int b[],int n)//传值
{
for(int i=0;i<n;i++)
{
a[i]=b[n];
}
}
int Swap(int *a,int *b,int n)//传指
{
for(int i=0;i<n;i++)
{
*(a+i)=*(b+i);
}
}
int Swap(int &a,int &b,int n)//传指
{
for(int i=0;i<n;i++)
{
a[i]=b[n];
}
}
//交换10w的数
int main()
{
int a[100000]={1…………100000};
int b [100000]={-1…………0};
}
1. 空间复杂度看,第一个 O(N) ,第二个 O (1) ,第三 没有开辟空间
2. 引用代码理解性来说更好理解,更安全,妈妈再也不用担心我会忘记解引用了
- 作返回值
引用也可以做返回值,但是他有一个限制,就是返回参数必须是出了你所调用的函数的作用域还没有销毁,换种说法就是你所返回的变量是不存在栈上的
俩份差不多一样的代码但是多一段 printf("/"); 为啥就变成随机值了呢?
先看看编译器是如何处理的
-
1.如何变量带回到主函数的呢?一般情况下入变量比较小就放在寄存器(复制一份返回变量,具有常性),比较大就会在main函数中临时开一块空间
-
2 . 且一个变量在函数中创建(没static修饰),那么他的函数结束他的生命周期也结束(就是销毁)
简单来说就是A 是Z的引用,Z被销毁了,编译器没有初始化这块空间
,那么返回就打印则不会有问题,在这期间做一些事情,这块区域重新使用
那打印就是有问题的
了解了上面的性质那那么就好理解了
上面说过小数据是通过寄存器回带的,上面知道数据出了作用域就会销毁,那么如果是你会怎么办,要是我就考一份,或者malloc,new一个,编译器采用的是第一种
如图:
但是有一个性质就是具有常性的,你想他不会修改那么给他搞成常量不过分吧
常引用
其实常量也是有引用的但是没啥用,应为常量是不可用改变的。那他的别名也是。因为引用是给他取别名,公用一块空间,从适配角度来说你要加一个&前加个const
int const &a=10;
那么返回值是具有常性的,那么你接收的时候也要是常引用
总结
- 缺省参数就是一层防护,你没穿参数会自动调用
- nullptr 代替NULL,他只表示为空指针(void*)0
- 引用是指针的plus版本
- 他和原数据公用一块空间
- 他必须初始化
- 且她不能像指针一样改变指向位置
- 且各便捷,可读性更高
- 做返回值的时候一定要确保这个数据出了当前函数作用域不销毁
- 这个在后面的类中会特别体现出来
以上是关于[C++潜心修炼] 小试牛刀的主要内容,如果未能解决你的问题,请参考以下文章