大家好,我是梁唐。
我们前面使用指针创建的都是单个变量,在这种情况下,使用指针的优势并不明显。很多程序员仍然会选择使用声明变量的方式,而当我们需要动态创建数组这种大型数据的时候,指针就能体现出优势了。
我们使用声明的方式创建的数组在编译时就已经分配好了内存空间了,即使我们在程序当中完全不使用,它也依然存在占用了资源。这种编译时给数组分配内存被称为静态联编(static binding),意味着数组是在编译时加入程序的。
而使用new创建的数组则是在运行时,我们前文也说过,两者最大的区别在于一个是栈内存一个是堆内存。我们可以用程序去控制它是否创建,以及在什么情况下创建,并且数组的长度。因此这种数组被称为动态数组(dynamic array),这种创建方式称为动态联编(dynamic binding)。
创建数组
使用new创建数组很容易,和声明的方式一样,只需要将数组的类型以及元素数量写明即可。
- int *arr = new int[10];
new运算符会申请一块10个int大小的内存,并且将第一个元素的地址进行返回给指针arr。
对于使用new创建的数组,我们同样也可以使用delete来释放,但需要注意的是,由于我们申请的是数组类型,所以在delete的时候也需要写明这是一个数组:
- delete [] arr;
如果不加方括号,那么delete仅仅会释放指针指向的元素也就是数组的第一个位置。所以我们在使用new和delete的时候一定要注意,在创建时如果使用了方括号申请了数组,那么在delete的时候也需要加上方括号。如果不匹配则可能会引发不确定的后果,所以千万要当心。
C++ Primer当中整理了几条规则,搬运过来:
- 不要使用delete释放不是new分配的内存
- 不要使用delete释放同一块内存两次
- 如果使用new[]为数组分配内存,则也应该使用delete[]来释放
- 如果使用new为非数组分配内存,应该使用delete来释放
- 对空指针delete是安全的
使用动态数组
聊完了delete的用法, 我们再来看看动态数组的使用。
这里有一个问题在于,我们通过new创建得到的虽然是一个数组,但是却是以指针的形式得到的,那么我们怎么来使用呢?
其实很简单,我们就当做和数组一样来使用就行了:
- int *p = new int[10];
- p[2] = 5;
- cout << p[2] << endl;
因为数组本质上就是常量指针,因此它们基本等价。唯一的不同在于数组是常量指针,所以我们不能对数组名进行赋值操作,而指针可以:
- p = p + 1;
- ++p;
是的,指针可以进行算术操作,对于指针进行加减操作其实等价于指针的移动。比如指针加一代表指向的元素向后移动一位。
原本p指针指向数组的下标0的位置,当p++之后,指向1的位置。因为数组是一块连续的内存,不同类型的变量的长度不同。因此在底层运算的时候,指针指向的位置移动的长度其实并不是1,而是一个变量类型占用的字节数。
同理,指针也可以做减法,得到的差是一个整数。这种运算只有两个指针指向同一个数组才有意义,代表两个指针之间间隔的元素数量。
本文转载自微信公众号「Coder梁」,可以通过以下二维码关注。转载本文请联系Coder梁公众号。