现代c++应尽量使用vector和迭代器类型,避免使用低级的数组和指针。设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针。
与vector类型相比,数组的显著缺陷在于L数组的长度是固定的,而程序员无法知道一个给定数组的长度,数组没有获得其容量大小的size操作,也不提供push_back操作在其中添加元素,
现在c++程序则更多的使用vector取代数组与程序内部使用,只有当性能测试表明使用vector无法达到必要的速度要求时,才使用数组,
包括整型,字面值常量。枚举常量,非const变量以及到运行阶段才知道其值的const变量都不能用于定义数组的维数。
没有所有的元素都是引用的数组。
在函数外定义的内置数组其元素均初始化为0;
在函数内定义的内置数组其元素无初始化。
应避免使用未初始化的指针。
对指针进行初始化或复制只能使用以下四种类型的值:
1) 0值常量表达式。
2) 类型匹配的对象的地址。
3) 另一个对象之后的下一个地址。
4) 同类型的另一个有效指针。
Void指针:
C++提供了一种特殊类型void*。它可以保存任何类型对象的地址。
Void指针值支持集中有限的操作:
1) 与另一个指针进行比较
2) 向函数传递Void*指针或从函数返回void*指针
3) 给另一个void指针赋值
4) 不允许使用void指针操纵它所指向的对象,
指针与引用的比较:
1) 引用总指向某一个对象:定义引用时没有初始化时错误的
2) 赋值行为的差异:给引用赋值修改的时该引用所关联的对象的值而不是是引用于另一个对象关联。应用一经初始化指向同一个特定的对象。
指针本身就是一种迭代器。
Const double *cptr;//cptr是一个指针,它指向double类型const对象。
Double *const cptr// cptr是一个const指针。它指向double类型对象。
Typedef string *pString;
Const pString cstr;
很多人认为是:const string *cstr;
这是错误原因是:声明const pString 时,const修饰的是pstring类型,这是一个指针。
所以const修饰的是指针。所以应该是:string *const cstr;
尽可能的使用C++标准库类型string,不必担心字符数组的大小问题。
对大部分的应用而言,使用标准库缧绁string,除了增强安全性以外,效率也提高了。
动态分配数组:
Int *pt = new int[10];
也可以初始化动态分配数组
Int *pt = new int[0]();//对于动态分配的数组,其元素只能初始化为元素类型的默认值,而不能像数组变量一样,用初始化列表为数组元素提供各不相同初值。
允许动态分配空数组:
虽然数组长度是固定的,但动态分配数组不必在编译时知道其长度,可以(通常也是)在运行时才确定数组长度。(一般数组在编译时必须知道其长度)
例如:int n=getSize(); int *p=new int[n]; for(int *q=p;q!=p+n;++q){*q…….}
动态空间的释放:delete[] p;//中间的[]不能去掉,它表示释放的是自由存储区中的数组,而并非单个对象。
标准库bitset类型(也是一种类模板)
在定义bitset是,要明确bitset含有多少位,需在尖括号内给出它的长度值;
Bitset<32> betvec;//32bit,all zero;
给出的长度值必须是常量表达式,另,和vector一样bitset中的为是没有命名的,程序员只能按位置来访问他们。危机的位置编号从0开始,因此,bitset的为序是从0到31;以0位开始的位串是低阶位,以31位结束的位串是高阶位;
初始化bitset对象的方法:
Bitset<n>b;//b有n位,每位都为0;
Bitset<n>b(u);//b是unsignedlong型u的一个副本
Bitset<n>b(s);//b是string型的s中含有的洧川的副本。
Bitset<n>b(s,pos,n);//b是s中从位置pos开始的n个位的副本。
当用unsigned long值作为bitset对象初始化值时,该值将转化为二进制的位模式。如果bitset类型长度大于unsigned long值的二进制位数,则其余的高阶位将置为0;如果小于只用低阶位,超过的被丢弃。
Bitset<16> bitvec(0xffff);//由于bitvec小于unsignedlong所以高阶位别丢弃;
Bitset<32> bitvec(0xffff);
Bitset<64> bitvec(0xffff);//高阶位填充为0;
0-15都是1;
当string对象初始化bitset对象时,string对象直接表示为位模式,从string对象读入危机的顺序是从右向左。
String str(“1100”);
Bitset<32> bitvec(str);//第2,3的位置为1,其余为0;如果对象的字符个数小于bitset类型的长度,则高阶位将置为0;
String对象和bitset对象之间是反向转化的,string对象的最右边字符下标最大,用来初始化bitset的最低位,正好相反。记住这一差别。
还可以这样:
String str(“1111111000000000”);
Bitset<32> bitvec(str,5,4);//从str[5]开始,赋值4位;
Bitset<32> bitvec(str,str.size(),-4);//用最后4位。
Bitset上的操作:
b.any();//b中是否存在1;
b.none();//b中不存在1吗
b.count();//b中1的个数
b.size();//中二进制位的个数
b[pos];//访问b中pos处的二进制位
b.test(pos);//pos处的二进制位是否为1
b.set();//吧b中的二进制位全置为1
b.set(pos);//将pos处的二进制位置为1
b.reset();//重置0
b.reset(pos);//将pos处置为0
b.flip();//将b所有二进制位取反
b.flip(pos);//将pos处取反
b.to_ulong();//将b转化为unsignedlong 类型
os<<b;//将b中的位集输出到os流;
可以用输出操作符输出bitset对象中位模式。
Bitset<32> bitvec(0xffff);
Cout<<”bitset:”<<bitset<<endl;
输出结果:0000000000000000011111111111111111
自增和自减:
有使用过c语言背景的读者可能会觉得奇快,为什么要在程序中使用前自增操作,道理很简单:因为前置操作需要做的工作更少只需加1后返回加1后的结果即可,而后置操作必须先保存操作数原来的值,以便返回未加1之前的值作为操作的结果。
后置操作符返回为加1的值:当我们希望在单个复合表达式中使用变量的当前值,然后再加1时,通常使用后置操作。
例如:vector<int>::iterator iter=ivec.begin();
While(iter!=ivec.end())
Cout<<*iter++;