动态数组
由于每个程序有自己的自由空间(free store)或称堆栈(heap),我们可以动态地为数组分配空间,这在C语言中通过malloc和free实现,而在C++中则由new和delete实现:
int *pia=new int[10]; //申请一个含有10个未初始化元素的整型动态数组
new返回在堆栈中的动态数组的首个元素地址,我们就可以用指针访问数组中的元素。如果动态数组是class类型,则用其默认的构造函数初始化,如果是内置类型则不初始化,与数组变量不同的是,无法对动态数组中的每一个元素分别初始化为不同的值,如果一定要初始化,只能用()对其初始化为0:
int *pia2=new int[10]();
由于是动态分配空间,就不必像数组变量类型一样必须在编译时就确定其大小,可以再程序运行时计算出大小,再分配相应的空间,所以如下程序是正确的:
size_t n=getsize(); //getsize返回所需数组大小
int *pia3=new int[n]; //n在编译时是不知道其值的
for (int *p=pia3; p!=pia3+n;++p)
//对数组进行操作
有人也许会担心万一getsize返回0,岂不是会出错?数组变量类型确实不能这样做,int a[0]的定义是不合法的,但是new int[0]是合法的,它会返回一个非0值指针,可用于比较,例如上面的程序,由于n=0,所以在第一次判断p!=pia3+n时即结束循环,程序可以正常执行,不会出错,这样的设计就是保证在程序执行时能够正确的动态分配数组大小不出错。
要释放动态数组的空间,要使用delete函数
delete [] pia; //注意[]一定不能省略,否则可能出错
String类和C风格字符串的混用
很多时候我们需要在C风格代码的基础上写C++代码,这样就需要将原来的C风格字符串转换为string类以供C++更好的使用,其实string可以用C风格字符串初始化:
char *str="hello world";
string str2="hello world"; //string类可以用字符串常量初始化
string str3=str; //string类也可以用字符串变量初始化
反过来,我们也可以将string类对象转换为字符串变量,但是只能是const char* 类型的:
const char *str4=str2.c_str(); //通过成员函数c_str()来实现
用数组变量初始化vector
与上面类似,我们也可以用C风格的数组变量初始化C++里的vector类,通过传递想要的第一个元素和最后一个元素的下一个位置来初始化:
size_t n=6;
int arr[n]={0,1,2,3,4,5};
vector<int> ivec(arr, arr+n);
多维数组
多维数组初始化可以在大括号里嵌套大括号,也可以按行一直排下去:
int a[3][4]={{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};
int a[3][4]={0,1,2,3,4,5,,6,7,8,9,10,11};
当然,也可以只初始化每行的头几个元素:
int a[3][4]={{0}, {1}, {2}}; //各行第0列元素被初始化
int a[3][4]={0,1,2}; //第0行前3个元素被初始化,注意与上面的不同,上面的大括号不能省略
多维数组中的指针定义:如果我们需要一个指向二维数组某行的指针,就需要这样定义:
int a[3][4];
int (*p)[4]=a; //p指向含四个整型变量的数组,此时是a的第0行
p=&a[2]; //p指向a的第2行
注意不要写成int *p[4],此为含有四个指向整型变量的指针的数组。
练习题4.36——用指针遍历二维数组a[3][4]
for (int (*p)[4]=a; p!=a+3; ++p)
for (int *q=*p; q!=*p+4; ++q)
cout<<*q<<endl;