数组名其实就是一个常指针,指向数组元素中第一个的地址,在程序中如果要用指针遍历数组,不能直接用数组名来自增或自减,因为它是常量,一般先把数组名保存一份同类型的指针,然后再用这个指针来自增或是自减来实现遍历。
指针也是可以进行算术加法和减法的,但必须保证原地址和结果地址都是想同一个数组的元素或是指向数组的末端元素的下一个单元(类似end())。
指针的减法操作是有意义的,它表示两个指针的相对位置关系,减法结果是ptrdiff_t类型,和size_t类型一样,是一种机器相关的类型,size_t是无符号的,用于表示下标;而ptrdiff_t是有符号的,表示相对位置的。
前面说道C++不检测数组的下标,所以p[-2]也不会在编译期抛错。(这个语法在VS2012下测试不通过,是因为编译器做了下标的合法性检测)
指向const对象的指针,const指针,与指向const对象的const指针。
指向const对象的指针可接受const对象或是非const对象,但都不能试图通过该指针来修改所指对象的值,当然非const对象可以用其他的方式来修改其值。一般函数传参时使用这种情况,防止函数内修改外部传的参数。
Const指针是一种const属性的变量,定义之初必须初始化,而且一经初始化就不能修改,也就是指针不能修改其指向。
指向const对象的ocnst指针是两者的结合。
指针与typedef的结合。
Typedef可以简化长类型名,尤其是在STL的模板中。
Typedef string *pstring; const pstring cstr;
上两行的代码中,cstr的类型是什么,直觉是conststring *cstr;但这是受了宏定义的文本替代的误导了,在这里typedef做的不是文本替代工作,而是产生名字上的新类型。
Pstring本身就是一种指针,用const修饰pstring,就意味着cstr是常指针,和string const *cstr;一致。
Strings;
Typedefstring *pstring;
Constpstring cstr1 = &s;
Pstringconst csre2 = &s;
Stringconst *cstr3 = &s;这三个表达式都是一个意思。
永远不要忘了字符串的null。
Char ca[] = {‘C’,‘+’,‘+’};
Cout<<strlen(ca)<<endl;输出的结果不可预料,因为ca没有以null结尾,strlen函数无法正常工作。
在对C风格字符串进行操作时保证每一次的操作后都要在目标字符串后添加null,因为大多数的字符串操作函数都会返回该目标字符串。
动态分配的数组的初始化,数组类型是类类型的调用默认构造函数,基本内置类型的不初始化。Int *pi = newint[10]();后面的括号可指示编译器为数组初始化为0。
Const int *pi1 = new const int[10];这句不对,因为const常量需要初始化。正确写法:const int *pi2 = new const int[10]();
不允许声明静态分配长度为0的数组,但可以动态分配长度为0的数组。
Int ia[0];是错
Int *pi = new int[0];在C++中是对的,new返回一个非零的指针,但该指针与其他返回的指针不同,该指针不能进行解引用。
String对象可以转换成C风格字符串,调用其c_str()函数,函数返回值类型是const char*,所以为了代码的严谨起见,需要用同类型的指针来接收。有一个问题是,string对象在后面修改了字符串内容,那之前c_str()函数返回的字符串就失效了,所以好的实践是:将c_str()函数返回的数组备份一份。
在C和C++中严格来说不存在多维数组,二维数组的本质是数组的数组,语言中只有一维数组。
Int ia[3][4] = { {1}, {2}, {3} };每一行的第一个值初始化为相应的值,其余的均为0
指针和多维数组的结合
Int ia[3][4];
Int (*pi)[4] = ia; 定义一个数组指针,数组长度是4的,数组指针不同的人维度代表不同的类型,int (*arr)[2]和int (*arr)[3]中的arr不是一个类型。
Pi = &ia[2]; 将ia数组的第三行地址取出,这里面涉及到二维数组的行指针和列指针之分,这里就是把列指针转换为了行指针
用typedef可以简化多维数组的定义
Typedefint int_array[4];
以后int_array就是长度为4的一维数组类型了。值得一提的是长度为4的一位数组和长度为5的一维数组不是同一个类型了。
Delete[]p;中的p必须是指向数组的第一个元素的指针。