一 默认参数
1、什么是默认参数
在定义函数时,可以在形参后面加上赋值;表示这个形参有一个默认值,如果调用函数时不传实参,则形参取默认值;
#include <iostream>
using namespace std;
int add(int a = 1, int b = 2)
{
return a+b;
}
int main()
{
cout << add() << endl;;
return 0;
}
结果:
3
2、注意点
(1)传参时顺序为从左往右,因此默认参数设置必须从右往左;
传参顺序为:若有实参则从第一个形参开始赋值,挨着赋值直到实参轮完;才会开始使用默认参数;如果形参列表中左边有默认值,最右边没有,而实参个数比形参少,那么最右边的形参没有传递值,则编译不通过;
(2)声明中写了默认参数,定义时不需要重复写;
(3)默认参数不能是引用;因为引用在定义后不能再改变引用对象;
(4)默认参数和函数重载一起使用,可能产生二义性问题,多加小心;
二 new & delete
C++引入这两个运算符用于动态申请和释放内存;
大致理解一下
new是一个运算符,后跟一个数据类型就能在堆上申请这个类型大小的空间并返回这块空间的首地址,返回的就是这个类型的指针;
delete是匹配的运算符,后跟new出来的指针,就能释放new出来的内存空间;
1、怎么用
new的基本用法
【1】类型 * 指针名 = new 类型
【2】类型 * 指针名 = new 类型(初值)
【3】类型 * 指针名 = new 类型 [个数]
第一种是申请一个类型大小空间,(基本类型不初始化,类的话会调用构造函数),(如果类的构造函数有形参,则应该使用【2】),返回首地址;
第二种是申请一个类型大小空间,(并用初值初始化),然后返回首地址;
第三种是申请[个数]个类型大小空间,返回首地址;(如果是基本类型如数组,不会初始化,而如果是类,则会调用构造函数);
简单讲就是()初始化;[]写数量;那么这俩能不能同时用呢?比如new(2)[3]或者new[3] (2);答案是不能,编译不通过,只能选【2】或者【3】中的一种,所以对于构造函数有形参的类,只能用【2】一个一个的申请;总结一下:
(1)对于类空间的申请,如果构造函数无形参,则可以用【1】或者【3】,如果有形参,则必须用()而且必须写实参,这意味着一次只能申请一个类对象空间,即只能【2】;
(2)对于基本类型如int,【1】【2】【3】都可以,需要说明的是:当用【3】时,可以在[个数]后跟(),但不能写实参,这表示讲这片空间都初始化为0;如int *p=new int2;则*p=0; *(p+1)=0;这不是【2】和【3】的混用;
哦,当然,有可能申请空间失败,则会返回一个NULL;但这种情况很少见;可以注意到new到的空间没有变量名,只能通过指针访问;
deltete的基本用法
【1】delete p;用于释放单变量地址空间;
【2】delete [] p;用于释放数组变量空间,[]内不写东西;
如果new的类型是类,则会调用析构函数;
基本注意点:
1、指针的类型必须是能指向new后所跟的类型单元;
int *p = new int;
int *p = new int [10];
int (*p)[10] = new int [3][10];
int (*p)[2][32] = new int [3][2][32];
2、new出的必须delete,如new出的类空间在堆上,其析构函数直到程序结束都不会自动调用,只能由delete来调用;
3、new出的空间只能通过指针访问;因此不能对这个指针进行自增等改值操作,这会导致程序找不到正确的空间地址;容易导致释放错误的空间或者无法释放堆区空间,即内存泄漏;
4、delete时不要造成重复释放,即对一个指针释放两次,很可能两次delete之间指针已经指向了其他有效空间;
5、delete只会释放空间,不会删除指针,也不会更改指针的指向,因此delete之后应该做置空,防止误访问;
int *p = new int[2];
cout << p << endl;
*p = 1;
*(p+1) = 2;
cout << *p << "," << *(p+1) << endl;
delete [] p;
//释放空间后再次访问
cout << *p << "," << *(p+1) << endl;
cout << p << endl;
结果:
0xec7128
1,2
15466688,15466688
0xec7128
2、深入一点
请看这位大佬的文章: