C++ 数组和指针学习总结(一)

2014-11-24 02:02:54 · 作者: · 浏览: 6
数组
定义及其初始化
1、数组的维数必须用值大于等于1的常量表达式定义(包括:整型字面值常量、枚举常量、用常量表达式初始化的整型const对象),非const变量以及到运行阶段才知道其值的const变量都不能用于定义数组的维数。
3、定义数组时没有显式的初始化,则:
----在函数体外定义的内置数组,元素均初始化为0
----在函数体内定义的内置数组,元素均无初始化
----无论在何处定义,若其元素为类类型,则自动调用其默认的构造函数初始化;若无构造函数,则必须为该数组的元素提供显式的初始化
2、字符数组可以使用字符串字面值进行初始化,但当使用字符串字面值来初始化字符数组时,将在数组后面加入空字符,例如:char A[] = "C++"; //A的维数是4
3、与vector不同,一个数组不能用另一个数组初始化,也不能将一个数组赋值给另一个数组
注意:数组长度固定,一旦定义,就无法添加新的元素。但是若要添加,则需要自己更改内存remalloc()以及malloc()函数可以实现
数组的操作
下标访问。下标的数据类型:size_t
指针
定义及其初始化
建议:尽量避免使用指针和数组
  指针和数组容易产生不可预料的错误。其中一部分是概念上的问题:指针用于低级操作,容易然生与繁琐细节相关的(book keeping)错误。其他错误则源于使用指针的语法规则,特别是声明指针的语法。
  许多有用的程序都可不使用数组或指针实现,现代C++程序采用vector类型和迭代器取代一般的数组、采用string类型取代C风格字符串。
指针可能的取值
  一个有效的指针必然是以下三种状态之一:保存一个特定对象的地址;指向某个对象后面的另一对象;或者是0值。若指针保存0值,表明它不指向任何对象。未初始化的指针是无效的,直到给该指针赋值后,才可使用它。
[cpp]
int ival = 1024;
 int *pi = 0;      // pi initialized to address no object
 int *pi2 = & ival;  // pi2 initialized to address of ival
 int *pi3; // ok, but dangerous, pi3 is uninitialized
 pi = pi2;       // pi and pi2 address the same object, e.g. ival
 pi2 = 0;        // pi2 now addresses no object
指针初始化和赋值操作的约束
  对指针进行初始化或赋值只能使用以下四种类型的值:
  (1)0值常量表达式。
  (2)类型匹配的对象的地址。
  (3)另一对象之后的下一地址。
  (4)同类型的另一个有效指针。
  把int型变量赋给指针是非法的,尽管此int型变量的值可能为0。
void*指针
  C++提供了一种特殊的指针类型void*,它可以保存任何类型对象的地址:
[cpp]
 double obj = 3.14;  
 
  double *pd = &obj;
  // ok: void* can hold the address value of any data pointer type
  void *pv = &obj; // obj can be an object of any type
  pv = pd; // pd can be a pointer to any type
----void*表明该指针与一地址值相关,但不清楚存储在此地址上的对象的类型。
----void*指针只支持几种有限的操作:与另一个指针进行比较;向函数传递void*指针或从函数返回void*指针;给另一个void*指针复制。
----不允许用void*指针操纵它所指向的对象。
指针操作以及指针有关注意事项
一、解引用操作生成左值
二、关键概念:给指针赋值或通过指针进行赋值
对于初学指针者,给指针赋值和通过指针进行赋值这两种操作的差别确实让人费解。谨记区分的重要方法是:如果对左操作数进行解引用,则修改的是指针所指向的值;如果没有使用解引用操作,则修改的是指针本身的值。
三、指针和引用的比较
第一个区别在于引用总是指向某个对象:定义引用时没有初始化是错误的。第二个重要区别则是复制行为的差异:给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象(这就是为什么引用必须在定义时初始化的原因)。
四、指向指针的指针
指针本身也是可用指针指向的内存对象。指针占用内存空间存放其值,因此指针的存储地址可存放在指针中。
[cpp]
int ia[] = {0, 2, 4, 6, 8};
 int *ip =ia; // ip points to ia[0]
 ip = &ia[4]; // ip points to last element in ia
 ip = ia; // ok: ip points to ia[0]
 int *ip2 = ip + 4; // ok: ip2 points to ia[4], the last element in ia
指针的算数操作只有在原指针和计算出来的新指针都指向同一个数组的元素,或指向该数组存储空间的下一单元时才是合法的。如果指针指向一对象,我们还可以在指针上加1从而获取指向相邻的下一个对象的指针。
五、C++还支持对这两个指针做减法操作:
[cpp]
ptrdiff_t n = ip2 - ip;  // ok: distance between the pointers
结果是4,这两个指针所指向的元素间隔为4个对象。两个指针减法操作的结果是标准库类型ptrdiff_t的数据。与size_t类型一样,ptrdiff_t也是一种与机器相关的类型,在cstddef头文件中定义。size_t是unsigned类型,而ptrdiff_t则是signed_t整型。
允许在指针上加减0,使指针保持不变。如果一指针具有0值,则在该指针上加0仍然是合法的,结果得到另一个值为0的指针。也可以对两个空指针做减法操作,得到的结果仍是0。
六、解引用和指针算术操作之间的相互作用
在指针上加一个整型数值,其结果仍然是指针。允许在这个结果上直接进行解引用操作,而不必先把它赋给一个新指针:
[cpp]
int last = *(ia + 4);  // ok: initializes last to 8, the value of ia[4]
加法操作两边用圆括号括起来是必要的。如果写为:
[cpp]
last = *ia + 4;// ok: last = 4, equivalent to ia[0]+4
意味着对ia进行解引