首先需要理解int a; int *a; int **a; int (*a)[10]; int *a[10];int (*a)(int);各自的含义,并学会区分
a) int a; 表示一个内存空间,这个内存空间用来存放一个整数(int)
b) int *a; 表示一个内存空间,这个内存空间用来存放一个指针,这个指针指向a)那样的内存空间
c) int **a; 表示一个内存空间,这个内存空间用来存放一个指针,这个指针指向b)那样的内存空间
d) int (*a)[10]; 表示一个内存空间,这个内存空间用来存放一个指针,这个指针指向一个长度为10、类型为int的数组
e) int *a[10]; 表示一个长度为10 、类型为int*的数组
f) int (*a)(int); 表示一个内存空间,这个内存空间用来存放一个指针,这个指针指向一个函数,这个函数有一个类型为int的参数,并且参数的返回值为int
注意int **a与int (*a)[N]的使用
int (*a)[N]和int **a在用法上的区别在于,++、+=1之后的结果不一样。
我们可以看如下代码:
int a[3][4];
int **p1 = a; // error
int (*p2)[4] = a; // ok
问题出在类型的对应上,而不是内容上。a的类型为& a[0]即一个指向长为4的数组的地址,所以可以赋值给int ()[4]类型(指向长为4的数组的指针)。而不能赋值给int *类型(指向指针的指针)。
数组作为形参
int a[2];
a代表的其实并不是数组的地址,而是数组第一个元素的地址,即& a[0];
int args[][2] = {{1, 2}, {3, 4}, {5, 6}};
// 下面4个输出都相同
cout<<&args<<endl;
cout<<args<<endl;
cout<<&args[0]<<endl;
cout<<&args[0][0]<<endl;
int c[3][4][5];
- c 的类型等价于int (*)[4][5] | c+1指的是c+sizeof(int)*4*5 ((c) [3][4][5])
- *c (等价于c[0])的类型等价于int (*)[5] | *c+1指的是*c+sizeof(int)*5 ((c[0]) [4][5])
- **c (等价于c[0][0])的类型等价于int *| **c+1指的是**c+sizeof(int*) ((c[0][0]) [5])
例子:
// 形参:指向2维数组的地址
# define N 2
void subfun(int subargs[][N], int m){}
int main(){
int args[][2] = {{1, 2}, {3, 4}, {5, 6}};
subfun(args, 3);
}
// 形参:指向2维数组的指针
# define N 2
void subfun(int (*subargs)[N], int m){}
int main(){
int args[][N] = {{1, 2}, {3, 4}, {5, 6}};
subfun(args, 3); // args相当于& args[0]
}
利用vector:
// 形参:2维vector的引用
void show_vector(vector<vector<int> > &vecTest) {
}
对比下列情况进行思考:
// 形参:指针的指针
void subfun(int **subargs, int m, int n){}
int main{
int *a[3];
int args[][2] = {{1, 2}, {3, 4}, {5, 6}};
// subfun(3, args)会报错,问题出在类型上,而不是内容上
for(int i=0;i<3;i++)
a[i] = args[i]; // 等价于 a[i] = & args[i][0]
subfun(a, 3, 2);
}
动态申请二维数组
传统方法:
// m*n
int main(){
int **p = new int*[m];
for(int i=0;i<n;i++)
p[i] = new int[n];
for(int i=0;i<n;i++)
delete []p[i];
delete []p;
}
利用vector:
// m*n
#include <vector>
int main(){
// 初始化全为0
vector<vector<int> > p(m, vector<int>(n));
}
二维数组初始化
传统:
// 1 2
// 3 4
// 5 6
int args[][2] = {{1, 2}, {3, 4}, {5, 6}};
// 0 0
// 0 0
// 0 0
// memset应用于非单字节类型,只能赋值为0或-1
#include<string.h>
int args[3][2];
memset(args, 0, sizeof(args));
// 1 1
// 1 1
// 1 1
// 目的是达不成的,因为memset是按字节赋值的, 而一个int占4个字节,这样每个int的4个字节都设为1了
#include<string.h>
int args[3][2];
memset(args, 1, sizeof(args));
利用vector:
// 1维vector
int main(){
int test[] = {1, 2, 3};
// test的前3个元素都赋给testV
vector<int> testV(test, test+3); // 1, 2, 3
// test的第1个元素(从0算起)到第2个元素都赋给testW,长度为2 == (test+3) - (test+1)
vector<int> testW(test+1, test+3); // 2, 3
// 内容拷贝构造
vector<int> testFake(testV); // 1, 2, 3
// 从第0个开始拷贝到第1个,长度为2
vector<int> subTestFake(testV.begin(), testV.begin()+2); // 1, 2
// 长度为l的vector,并初始化为0
vector<int> zeroV(l);
// 长度为l的vector,并初始化为1
vector<int> zeroV(l, 1);
}
// 2维vector
int main(){
// m x n,初始化为0
vector<vector<int> > w0(m, vector<int>(n));
// m x n, 初始化为1
vector<vector<int> > w1(m, vector<int>(n, 1));
// 利用数组进行初始化
int args[][2] = {{1, 2}, {3, 4}, {5, 6}};
vector<vector<int> > wA(3, vector<int>(2));
for(int i=0;i<3;i++)
for(int j=0;j<2;j++)
wA[i][j] = args[i][j];
}
// 1
// 3 3
// 5 5 5
int main(){
vector<vector<int> > test;
for(int i=1;i<=3;i++)
test.push_back(vector<int>(i, 2*i-1));
}