|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
1.函数参数的默认值(缺省参数)
1.1概念
定义或者声明一个函数时,可以给这个函数的参数指定一个默认的初始值,调用这个函数的时候,如果不给这个参数传入值,则使用默认值。如果给这个参数传入值 则会替代掉默认值。
- #include <iostream>
- using namespace std;
- int getmax(int x=10,int y=100);
- int main()
- {
- cout << getmax() << endl;//100
- cout << getmax(200) << endl;//第一个参数赋值200,第二个默认值100
- cout << getmax(55,66) << endl;//66
- }
- int getmax(int x,int y)
- {
- return x>y?x:y;
- }
复制代码
1.2参数默认值使用的注意事项
1.2.1如果函数的某一个参数有默认值,那么该参数右边的所有参数都必须有默认值(靠右原则)
- int getmax(int x=10,int y);//错误
复制代码
1.2.2不要和重载形成调用冲突
- getmax(int x,int y=200);
- getmax(int x,int y,int z);
- cout << getmax(100) << endl;//调用第一个getmax
- cout << getmax(200,100) << endl;//调用第一个getmax
- cout << getmax(55,66,77) << endl;//调用第二个getmax
- //但是如果把getmax(int x,int y,int z);稍微更改
- getmax(int x,int y,int z=0);
- cout << getmax(55,66) << endl;//那么这时候无法确定会调用哪一个getmax
复制代码
1.2.3函数的默认值是在编译阶段阶段解决的,因此只能用常量、常量表达式或者全局变量等非局部化的数值作为函数的默认值
- int a = 100;
- void fishc(int a = g,int b = 100+23);
- void fishc(int a,int b =a);//错误
复制代码
1.2.4当函数的声明和实现分开时,则需要在声明中指定默认值,实现中不要再指定默认值。
- #include <iostream>
- using namespace std;
- //int getmax(int x,int y);错误
- int getmax(int x=10,int y=100);
- int main()
- {
- cout << getmax() << endl;//100
- cout << getmax(200) << endl;//第一个参数赋值200,第二个默认值100
- cout << getmax(55,66) << endl;//66
- }
- //int getmax(int x=10,int y=100)错误
- int getmax(int x,int y)
- {
- return x>y?x:y;
- }
复制代码
2.内联函数(inline)
2.1为什么要引入内联
函数底层调用时会在内存中不断跳转,会造成一定的时间和空间方面的开销,从而影响程序执行效率,特别是对于一些函数体代码不是很大,但又频繁地被调用的函数来说,解决其效率问题尤为重要。引入内联函数实际上就是为了解决这一问题。
2.2类比C语言中的宏函数(带参宏)
- #include <iostream>
- using namespace std;
- #define GETMAX(X,Y) ((X)>(Y)?(X):(Y))
- int main()
- {
- cout << GETMAX(100,200) << endl;
- int x=123;
- int y=345;
- cout << GETMAX(x,y) << endl;
- cout << GETMAX(y,x) << endl;
- }
复制代码
2.3原理
内联就是用函数已被编译好的二进制代码,替换对该函数的调用指令,更通俗点说,就是在编译时,请求编译器把函数的代码复制到调用位置。请求成功,就使用空间换取时间,请求不成功 则成为普通函数调用。
内联在保证函数特性的同时,避免了函数调用的开销,通过牺牲代码空间,赢得了运行时间
内联通常被视为一种编译优化策略
2.4具体运用
在需要内联的函数前面加上inline
- #include <iostream>
- using namespace std;
- inline int getmax(int x,int y)
- {
- return x>y?x:y;
- }
- int main()
- {
- cout << getmax(100,200) << endl;
- }
复制代码
2.5隐式内联和显式内联
2.5.1隐式内联
若函数在类或结构体的内部直接定义,则该函数会被自动优化为内联函数
2.5.2显式内联
若在函数定义前面加上inline关键字,可以显式告诉编译器,该函数被希望优化为内联函数
2.6内联的适用条件和一些问题
2.6.1使用条件
内联会使可执行文件的体积和进程代码的内存变大,因此
小函数,频繁调用,适合内联
大函数,稀少调用,不适合内联
递归函数,无法实现内敛
2.6.2一些问题
inline关键字仅仅代表一中对函数实施内联优化的期望,但该函数是否真的会被处理为内联函数,还要由编译器的优化策略决定
3.c++中的动态内存分配
3.1操作符
c++提供了new和delete操作符,分别用于动态内存的分配和释放
3.2分配单个变量对应的内存
- 类型 *指针名 = new 类型名;
- 类型 *指针名 = new 类型名();
- 类型 *指针名 = new 类型名(值);//初始化的值
- /* 释放堆内存 */
- delete 指针名;
复制代码- #include <iostream>
- using namespace std;
- int main()
- {
- int *p = new int;
- *p = 10;
- cout << *p << endl;
- delete p;
-
- p = new int(100);
- cout << *p << endl;
- delete p;
-
- return 0;
- }
复制代码
3.3分配多个变量对应的内存,类似数组的方式进行分配与释放
申请n个类型变量对应的堆内存
类型 *指针名=new 类型[n];
/* 释放这块堆内存 */
delete[] 指针名;
- int *p = new int[4]{1,2,3,4};
- /*字符数组一个只能初始化一个字符,而且此时指针保存的并不是整个字符串的首地址
- 而只是第一个字符的地址,所以拿指针进行打印,只能打印出来一个字符
- delete[] p;
复制代码
3.4定位内存分配(了解)
- char data[100];
- int *pdata=new (data)int[25];
复制代码
pdata 的内存指向栈中,不用考虑释放问题
并且pdata 和 data的地址是相同的
3.5内存分配的一些细节
3.5.1某些c++实现,用new操作符动态分配内存时,会在数组首元素前面多分配4或8个字节,用以存放数组的长度,new操作符所返回的地址是数组首元素地址,而非分配内存的首地址
3.5.2如果new操作符的地址直接交给delete处理,将导致无效指针(invalidate pointer)异常,使用delete[]操作符会将交给它的地址向低地址方向偏移4或8个字节,避免了无效指针异常的发生
3.5.3重析构
不能通过delete操作符释放已经释放过的内存
- int* p = new int;
- delete p;
- delete p;//核心转储
- //标准库检测到重析构(double free)异常后,将进程杀死,并转储进程映像
复制代码
3.5.4不建议与C语言中的动态内存分配函数混用,它会带来不可预知的问题。
4.引用(reference)
4.1概念
引用实际上就是一个变量的别名
4.2语法
/* 引用必须初始化 */
类型& 变量名=变量;
/* 引用一旦初始化之后,在引用的生命期内就不能更改引用的对象*/
- #include <iostream>
- using namespace std;
- int main()
- {
- int x=100;
- int& rx=x;
- cout << &x << endl;
- cout << &rx << endl;
- rx=1001;
- cout << x << endl;
- x=10001;
- cout << rx << endl;
- int y=111;
- int& rrx=rx;
- /* 这不是引用y 只是把y的值复制给 rrx */
- rrx=y;
- rrx=121;
- cout << y << endl;
- }
复制代码
4.3引用的应用
4.3.1引用型的函数参数
以前c当中,有过用函数交换两个变量的值,可以通过指针值传递,那么现在可以使用引用传递了
引用传递:参数的类型是引用类型
- #include <iostream>
- using namespace std;
- void myswap(int x,int y)//无法交换
- {
- int temp=x;
- x=y;
- y=temp;
- }
- void myswap2(int * x,int * y)//指针传递
- {
- int temp=*x;
- *x=*y;
- *y=temp;
- }
- void myswap3(int& x,int& y)//引用传递
- {
- int temp=x;
- x=y;
- y=temp;
- }
- int main()
- {
- int x=10;
- int y=20;
- // myswap2(&x,&y);
- myswap3(x,y);
- cout << x << '/' << y << endl;
- }
复制代码
通过引用传递参数,形参只是实参的别名而非副本,这就避免了从实参到形参的对象复制,这对于具有复杂数据结构的参数类型而言意义非常
4.3.2常量无法作为引用型参数传递,但是如果引用参数前加const就可以使用常量
如果函数内部不对数据进行修改则建议对参数写成const引用,这样除了防止修改,还增强了函数的兼容。
- void printNum(const int& x)//void printNum(int& x),如果函数是这样,程序报错
- {
- cout << x << endl;
- }
- int main()
- {
- printNum(200);
- const int z=100;
- printNum(z);
- }
复制代码
4.3.3引用类型的返回值
函数的返回值一般用来做右值,如果希望做左值,可以使用指针,或者使用引用。
注意不要返回局部变量的引用。可以返回static全局变量,堆中的数据,成员变量,引用型参数。
- #include <iostream>
- using namespace std;
- int* getmax(int* x,int* y)//用指针方法让函数返回值做左值
- {
- return *x>*y?x:y;
- }
- int& getmax(int& x,int& y)//引用的方法
- {
- return x>y?x:y;
- }
- int& getNum()
- {
- // static int x=155;
- int *x=new int(168);
- return *x;
- }
- int main()
- {
- int z=100;
- int x=10;
- int y=20;
- // *(getmax(&x,&y))=z;
- getmax(x,y)=z;
- cout << y << endl;
- cout << getNum() << endl;
- }
复制代码
4.4引用的底层实现
通过上面的代码,应该容易推断出,引用的底层实现就是指针
4.5引用和指针的联系与区别 (待补充)
下期预告:c++中的类型转换,类和对象,类的定义与实例化,构造函数与初始化表
新坑预告:明天可能会发win32程序开发相关的笔记,求支持 |
评分
-
查看全部评分
|