今天在编程的时候,遇到这样一条语句”delete [] p;”,回想之前使用delete基本上都是采用的”delete p;”的方式,比较好奇这两种语句的区别。查找相关资料资料之后,决定进一步地把C++中最为常见的符号“[]”的作用进行总结。
一般来说,“[]”的作用一共有三种:
1.
声明变量时使用“[]”,表示数组。如下所示:
int a[5]; //定义了一个大小为5的整型数组
int a[]={1,2,3,4,5}; //定义一个整型数组并初始化
int *p=new int[size]; //申请一个动态整型数组,数组长度由变量size决定
int (*a)[10]; //定义一个数组指针,注意:*a表明a是指针类型,而[10]则表明a指向的是一个大小为10的数组。
int *a[10]; //这一条与上一条对比来看,同样表示了一个大小为10的数组,不过数组元素均是指向整型变量的指针,故称为指针数组。
2.
表示下标运算。如下所示:
int *p;
p[1]=2;
上面的语句不难理解:定义了一个指向整型变量的指针p,由于指针变量中保存着地址,通过“地址+[]”的运算即可给下一地址赋值2.
关于指针与地址再多写一些。记得刚学c语言的时候,为这两者之间的关系困惑了很久。后来我们老师是这样解释的:你可以创建一个整型变量a来存储整型数,同样也可以创建指针(变量)来存储相应数据地址。你可以使用整型变量a进行各种运算,如(a+2)*3,同样地,指针也可以“代表”数据地址进行各种处理,譬如上面的p[1]=2.
STL中的一些模板,也重载了[]运算符,如vector和map。
3.
指示指针。这种用法一般是在数组作为函数参数时会用到。如下所示:
void fun(int a[]); //[]说明a是一个指针变量
void fun(int a[][10]); //前一个“[]”说明a是指针类型,后一个“[]”则说明指针数组的大小为10.这里的“数组”指的是由二维数组行向量构成的一维数组。这种书写方式一般是在二维数组作为函数参数调用时会用到,此处的10即代表的是数组第二维的大小。需要注意的是,第二维的大小必须明确。
void fun(int (*a)[10]); //这种写法和上面是等价的。同样,必须规定第二维的大小。第一维的大小则不受限制,甚至会被编译器“忽略”。例如,你定义了一个函数void func(int a[3][10]),如果此时实参是b[5][10],也可以通过编译,即使它的第一维长度5超过了形参的一维长度3;而如果实参是b[3][8],则不会编译通过,因为它们的第二维长度不一致。
值得注意的是,void fun(int **p)与上式的含义是不一样的。这里的p表示的是指针的指针,是“二重”的指针,与int *a[10]中的a是一个意思;而void fun(int a[][10])中的a是二维数组的行向量构成的一维数组的指针,归根结底是“一重”的指针。
————————————————————我是分割线———————————————————
回到最开始提到的问题:delete p与delete[] p到底有什么区别?查阅资料可知,这两种用法分别是operator delete函数的两个重载版本。
通常来说,如果p指向的是单个对象的话,应当调用delete p,以释放内存;如果p指向的是一组对象的内存地址的话,则应当调用delete[] p,可以达到逐个调用每个对象的析构函数,再释放内存的效果。在第二种情况下,如果还是使用delete p语句,则除p[0]之外对象的内存没有得到释放,会造成内存泄漏。
需要注意的是,如果p指向的一组对象都是像int/long/float一类的简单数据类型,由于它们没有析构函数,因此此时使用delete p与使用delete[] p的效果是一致的。