[C++ Primer 第4版]第4章 数组和指针

来源:互联网 发布:好看的日剧 知乎 编辑:程序博客网 时间:2024/05/29 19:32

P95 设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针。

P96 数组的维数必须用值大于等于1的常量表达式定义。此常量表达式只能包含整型字面值常量枚举类型或者用常量表达式初始化的整型const对象。非const对象以及要到运行阶段才知道其值的const变量都不能用于定义数组的维数。

P97显式初始化数组元素:在定义数组时,可为其提供一组用逗号分隔的初值,这些初值用花括号{}括起来,称为初始化列表。此时编译器会根据列出的元素个数来确定数组的长度。如果指定了数组维数,那么初始化列表提供的元素个数不能超过维数值。如果维数大于列出的元素初值个数,则只初始化前面的数组元素;剩下的其他元素,若是内置类型则初始化为0,若是类类型则调用该类的默认构造函数进行初始化。

P97特殊的字符数组:字符数组既可以用一组由花括号括起来、逗号隔开的字符字面值进行初始化,也可以用一个字符串字面值进行初始化。然而,字符串字面值包含一个额外的空字符(null)用于结束字符串。

P98 与vector不同,一个数组不能用另外一个数组初始化,也不能将一个数组赋值给另一个数组。

P99 数组下标的正确类型时size_t(vector下标的正确类型时vector::size_type)。


P100 与迭代器不同的是,指针用于指向单个对象,而迭代器只能用于访问容器内的元素。

P101 取地址操作符只能用于左值。

P103 如果可能的话,除非所指向的对象已经存在,否则不要先定义指针,这样可避免定义一个未初始化的指针;如果必须分开定义指针和其所指向的对象,则将指针初始化为0。

P103 对指针进行初始化或赋值只能使用以下四种类型的值:

(1)0值常量表达式;

(2)类型匹配的对象的地址;

(3)另一对象之后的下一地址;

(4)同类型的另一个有效指针。

          把int型变量赋给指针式非法的,但允许把数值0或在编译时刻获得0值得const量赋给指针。除了使用数值0或在编译时值为0的const量外,还可以使用C++语言从C语言中继承下来的预处理器变量NULL,该变量在cstdlib头文件中定义,其值为0。

P104 C++提供了一种特殊的指针类型void*,它可以保存任何类型对象的地址。void* 指针只支持几种有限的操作:与另一个指针进行比较;向函数传递void*指针或从函数返回void*指针;给另一个void*指针赋值。不允许使用void*指针操纵它所指向的对象。

P105 定义引用时没有初始化是错误的。

P106 C++使用**操作符指派一个指针指向另一个指针。

P107 指针的算术操作只有在原指针和计算出来的新指针都指向同一个数组的元素,或指向该数组存储空间的下一单元时才是合法的。

P107 两个指针减法操作的结果是标准库类型ptrdiff_t的数据。与size_t类型一样,ptrdiff_t也是一种与机器相关的类型,在cstddef头文件中定义。size_t是unsigned类型,而ptrdiff_t则是signed整型

P108 使用下标访问数组时,实际上是 使用下标访问指针/对指向数组元素的指针做下标操作。只要指针指向数组元素,就可以对它进行下标操作:

        int *p = & ia[2];

        int j = p[1];//p[1] equivalent to *(p+1), p[1] is the same element as ia[3]

P109 C++允许计算数组或对象的超出末端的地址,但不允许对此地址进行解引用操作。而计算数组超出末端位置之后或数组首地址之前的地址都是不合法的。

P110~P112 指向const对象的指针 &const指针 &指向const对象的const指针

(1)C++强调要求指向const对象的指针也必须具有const特性:

        const double *cptr;//cptr may point a double that is const

        const限定了cptr指针所指向的对象类型,而非cptr本身。也就是说,cptr本身并不是const。在定义时不需要对它们进行初始化,如果需要的话,允许给cptr重新赋值,使其指向另一个const对象。但不能通过cptr修改其所指对象对的指。

       不能使用void *指针保存const对象的地址,而必须使用const void *类型的指针保存const对象的地址。

       不允许把    const对象的地址 赋给 非const对象的指针;

       允许把    非const对象的地址 赋给 const对象的指针,但不能使用该const对象的指针修改非const对象的值。

(2)const指针本身的值不能修改,必须在定义时初始化。

        int *constcurErr = &errNumb;

        指针所指对象的值能否修改完全取决于该对象的类型。

(3)const double pi = 3.14159;

         const double*const pi_ptr = π

P112 指针和typedef

         理解复杂的const类型的声明

P113 尽管C++支持C风格字符串,但不应该在C++程序中使用这个类型。C风格字符串常常带来许多错误,是导致大量安全问题的根源。

P113 字符串字面值的类型就是const char类型的数组。

P113 C风格字符串是以空字符null结束的字符数组。

P113 C++语言通过(const) char*类型的指针来操纵C风格字符串。

P114 操纵C风格字符串的标准库函数

        strlen(s)//返回s的长度,不包括字符串结束符null

        strcmp(s1, s2);//比较两个字符串s1和s2是否相同。若s1与s2相等,返回0;若s1大于s2,返回正数;若s1小于                                      s2,返回负数

        strcat(s1, s2);//将字符串s2连接到s1后,并返回s1

        strcpy(s1, s2);//将s2复制给s1,并返回s1

        strncat(s1, s2, n);//将s2的前n个字符连接到s1后面,并返回s1

        strncpy(s1, s2, n);//将s2的前n个字符复制给s1,并返回s1

        要使用这些标准库函数,必须包含相应的C头文件:

        #include <cstring>

        传递给这些标准库函数例程的指针必须具有非零值,并且指向以null结束的字符数组中的第一个元素。

        如果必须使用C风格字符串,则使用标准库函数strncat和strncpy比strcat和strcpy函数更安全。

P114 C++语言提供普通的关系操作符实验标准库类型string对象的比较,这些操作符也可用于比较C风格字符串的指针,但效果却很不相同:实际上,此时比较的是指针上存放的地址值,而并非它们所指向的字符串。

P117 数组类型的变量有3个重要的限制:

(1)数组长度固定不变;

(2)在编译时必须知道其长度;

(3)数组只在定义它的块语句内存在。

          相比之下,动态分配的数组

(1)虽然长度时固定的,但不必在编译时知道其长度,可以(通常也是)在运行时才确定数组程度;

(2)将一直存在,知道程序显示释放它为止。

P117 动态分配数组时,只需指定类型和数组长度,不必为数组对象命名,new表达式返回指向新分配数组的第一个元素的指针:

        int *pia = new int[10];//array of 10 uninitialized ints

P117 动态分配数组时,如果数组元素具有类类型,将使用该类的默认构造函数实现初始化;如果数组元素是内置类型,则无初始化。也可使用跟在数组长度后面的一对空圆括号,对数组元素做值初始化。

P118 如果不再需要使用动态创建的数组,程序员必须显式地将其占用的内存空间返还给程序的自由存储区。

        delete []  pia;

P121 通常,由于C风格字符串与字符串字面值具有相同的数据类型,而且都是以空字符null结束,因此可以把C风格字符串用在任何可以使用字符串字面值的地方:

(1)可以使用C风格字符串对string对象进行初始化或赋值;

(2)string类型的加法操作需要两个操作数,可以使用C风格字符串作为其中的一个操作数,也允许将C风格字符串用作复合赋值操作的右操作数。

     反之则不成立:在要求C风格字符串的地方不可直接使用标准库string类型对象。但string类提供了一个名为c_str的成员函数,返回C风格字符串,其字面意思是:“返回C风格字符串的表示方法”,即返回指向字符数组首地址的指针,该数组存放了与string对象相同的内容,并且以结束符null结束。

P121 使用数组初始化vector对象,必须指出用于初始化式的第一个元素以及数组最后一个元素的下一个位置的地址。

0 0
原创粉丝点击