首先看一下c++里的动态创建数组
int* p_array = new int[10];
new运算符返回第一个元素的地址, 也就是会把数组的第一个元素的地址赋给指针p_array
当使用完new分配的内存时, 应该使用delete来释放他们:
delete[] p_array;
注意new分配内存的时候如果是[], delete的时候也需要加[]
动态创建数组相比与静态创建数组的区别是: 动态创建数组只有在需要的时候才会去真正申请内存空间
看一个简单的例子:
#include "iostream"
using namespace std;
int main() {
// 通过new来分配的内存时动态加载的,
double* p_double = new double[3];
// c++里可以将指针当做数组的名称一样使用, 来访问数组中的元素
// 这是因为c++里数组本身就是用指针来处理的
p_double[0] = 1.1;
p_double[1] = 1.2;
p_double[2] = 1.3;
cout << "p_double[1] = " << p_double[1] << endl;
// 下面的代码展示了指针和数组名的不同
// 可以对指针进行加减操作, 相当于将指针向后/向前移动
// 这行的+1 就相当于指针指向了数组的第二个元素
// +1增加的量, 相当于指针指向的类型的字节数
p_double = p_double + 1;
cout << "Now p_double[0] = " << p_double[0] << endl;
cout << "Now p_double[1] = " << p_double[1] << endl;
// 之所以要-1后再释放数组空间, 是因为new的时候是3
// 所以释放的时候也需要释放完全
p_double = p_double - 1;
delete [] p_double;
return 0;
}
程序的运行结果:
c++允许对指针和整数相加, +1 的结果相当于在原来的基础上加上指针指向的对象所占的字节数
再看一个数组和指针相互关系的例子:
#include "iostream"
using namespace std;
int main(){
double d_arr[] = {100.0, 200.0, 300.0};
short s_arr[] = {1, 2, 3};
// 两种将数组的首地址赋值给指针变量的方式
// 1.将数组名赋值给指针变量
double* p_d_arr = d_arr;
// 2.将数组的第一个元素的首地址赋值给指针变量
short* p_s_arr = &s_arr[0];
cout << "p_d_arr = " << p_d_arr << ", *p_d_arr = " << *p_d_arr << endl;
// 指针向后移动了8个字节, 也就是指向了数组的第二个元素
p_d_arr = p_d_arr + 1;
cout << "add 1 to the p_d_arr pointer : " << endl;
cout << "p_d_arr = " << p_d_arr << ", *p_d_arr = " << *p_d_arr << endl;
cout << "p_s_arr = " << p_s_arr << ", *p_s_arr = " << *p_s_arr << endl;
p_s_arr = p_s_arr + 1;
cout << "add 1 to the p_s_arr pointer : " << endl;
cout << "p_s_arr = " << p_s_arr << ", *p_s_arr = " << *p_s_arr << endl;
cout << "*********************************" << endl;
cout << "s_arr[0] = " << s_arr[0] << ", s_arr[1] = " << s_arr[1] << endl;
cout << "*s_arr = " << *s_arr << ", *(s_arr + 1) = " << *(s_arr + 1) << endl;
cout << "size of d_arr = " << sizeof(d_arr) << endl;
cout << "sizeof(p_d_arr) = " << sizeof(p_d_arr) << endl;
}
运行结果如下:
从程序的运行结果可以看出:
从运行结果可以看出:
- 一般情况下c++把数组名解释为数组的第一个元素的地址(10~12行代码)
- 如果arr是数组名, 那么arr[i] 被解释为*(arr + 1)
- p_d_arr = p_d_arr + 1运行情况就是将指针移动到数组的下一个元素的地址(在这里是向后移动了8个字节)
- 还可以看出s_arr [1] 等价于*( s_arr + 1), 也就是c++在遇到s_arr[1]的时候会相当于做了*(s_arr + 1)这种操作.
- 指针和数组名的区别就是数组名是常量, 而指针是可以修改指针的值的(也就是可以对指针进行加减等操作), 另外对数组名进行sizeof得到的是数组的长度, 而对指针进行sizeof得到的是指针的长度
再看一个更为详细的数组和指针的相互关系的demo:
#include "iostream"
using namespace std;
int main(){
short s_arr[10] = {1, 2, 3};
// 由于s_arr是数组名,也就是相当于指针, 指向数组的首地址
cout << s_arr << endl;
// 输出数组的第一个元素
cout << s_arr[0] << endl;
// s_arr相当于指针, *指针 也就是指针指向的地址里的元素
cout << *s_arr << endl;
// 数组第一个元素的地址
cout << &s_arr[0] << endl;
// 由于s_arr相当于指针所以&s_arr 相当于首元素的地址
cout << &s_arr << endl;
cout << "************" << endl;
// 由于s_arr相当于指针, 而又指向的是short型数组
// 因此+1相当于向后移动了两个字节
cout << "s_arr + 1 = " << s_arr + 1 << endl;
// &s_arr指向的是一个20个字节内存块的地址
// 因此&s_arr + 1, 相当于加了20个字节的地址
cout << "&s_arr + 1 = " << &s_arr + 1 << endl;
cout << "*************" << endl;
// 和&s_arr类似, 也就是p_short这个指针指向了一个20个字节内存块的地址
short (*p_short)[10] = &s_arr;
// p_short的地址和s_arr一样
cout << "p_short = " << p_short << endl;
// 输出s_arr地址
cout << "&s_arr = " << &s_arr << endl;
// 输出s_arr首元素的地址
cout << "&s_arr[0] = " << &s_arr[0] << endl;
// 输出s_arr首元素
cout << "s_arr[0] = " << s_arr[0] << endl;
// 由于p_short指向的是&s_arr, 因此*p_short 就和 s_arr一样
cout << "(*p_short)[0] = " << (*p_short)[0] << endl;
cout << "p_short + 1" << p_short + 1 << endl;
}
运行的结果为:
注意:数组名被解释为数组的第一个元素的地址, 而对数组名应用地址运算符(&)的时候, 得到的是整个数组的地址.
看上面的运行结果, 虽然说s_arr和&s_arr的地址相同, 但是代表的含义不同, s_arr代表的是数组首元素的地址, 而&s_arr代表的是一个20字节内存块的地址, 所以&s_arr + 1 实际加的是20个字节