博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C++ Primer 读书笔记 Chapter 4 数组和指针

Posted on 2010-08-17 01:27  KurtWang  阅读(403)  评论(0编辑  收藏  举报
  1. 数组定义和初始化
    1. 维数:必须为整型字面值常量,枚举常量或者常量表达式初始化的整型const对象。非const变量和直到运行阶段才知道的其值的变量不能作为维数(例如const unsigned sz=get_size(),sz虽然是const,但直到运行时刻才知道值,所以sz不能用作维数)。
    2. 如果没有显式初始化:
      1. 在函数体外定义的内置类型数组,元素均被初始化为0;
      2. 在函数体内定义的内置类型数组,无初始化;
      3. 不管定义在哪里,类类型都会调用默认构造函数进行初始化,如果没有默认构造函数,则必须为该数组的元素提供显式初始化
    3. 字符串字面值包含一个额外的\0,char ca[] = “C++”, ca的维度为4, char ca={‘C’, '+’, '+’ } ca维度为3
    4. 数组不能直接复制和复制;int ia[] = {0,1,2}; int ia2(ia);(错) int ia3[3]; ia3=ia; (错)
  2. 指针
    1. 指针声明语句,从右向左阅读。例:int ip, *ip2; ip为int, ip2为int*
    2. 指针若为0,则表明它不指向任何对象
    3. 把int值赋给指针是非法的,但允许把数组0或编译时可获得0值的const量赋给指针。int zero=0; const int c_ival=0; int * pi=zero; (错)pi=c_ival; (对)
    4. 指针和引用比较:
      1. 引用总是指向某个对象,引用必须在定义时初始化
      2. 给引用赋值是修改该引用所关联的对象的值,给指针赋值是更改该指针指向的对象
    5. 指针的差的类型为ptrdiff_t
    6. 指针下标:只要指针指向数组元素,就可以对他进行下标操作:int *p=&ia[2]; int k=p[-2]; (k是ia[0])
    7. C++允许计算数组或对象的超出末端的地址,但不允许对此地址进行解引用。计算超出末端位置之后或数组首地址底之前的地址都是不合法的。
        int arr[5]={1,2,3,4,5}; 
        int *p = arr;
        int *p2 = p+5; //合法
        int *p3 = p+6; //不合法
  3. 指针和Const
    1. 指向const对象的指针:
        const double pi = 3.14;
        double * ptr = π //错误
        const double * ptr = π //正确
        *ptr = 42; //错误
        
        double dval = 3.14
        ptr = &dval; //正确,可以将非const对象的地址赋给指向const对象的指针
    2. const指针:指针本身不能修改
        int num = 0;
        int num2 = 0;
        int * const cur = #
        *cur = 1; //正确
        cur = &num2; //错误,const指针,指针本身不能被修改
  4. C风格字符串,标准库函数 #include <cstring> 或 C风格:#include <string.h>
    1. strlen(s)
        int strlen(const char *str)
        {
          assert(str != NULL);
          int len = 0;
          while((*str++) != '\0')
        	len++;
          return len;
        }
    2. strcmp(s1, s2)
        int strcmp(const char *dest, const char *source)  
        {  
           assert((NULL != dest) && (NULL != source));  
           while (*dest && *source && (*dest == *source))  
           {  
               dest ++;  
               source ++;  
           }  
           return *dest - *source;  
           /*如果dest > source,则返回值大于0,如果dest = source,则返回值等于0,如果dest < source ,则返回值小于0。*/
        } 
    3. strcat(s1, s2)
        char* strcat(char *str1,char *str2)
        {
            char* tempt = str1;
            
            while(*str1!='\0')
            {
                str1++;
            }
            
            while(*str2!='\0')
            {
                *str1 = *str2;
                str1++;
                str2++;
            }
            
            *str1 = '\0';
            return tempt;
        }
        
    4. strcpy(s1, s2)
        char *strcpy(char *strDestination, const char *strSource)
        {
          assert(strDestination && strSource);
          char *strD=strDestination;
          while ((*strDestination++=*strSource++)!='\0');
          return strD;
        }
        
    5. strncat(s1, s2, n)
    6. strncpy(s1, s2, n)
  5. 创建动态数组:动态分配的对象放在堆(Heap)中。C中用malloc和free,C++用new和delete
    1. 如果数组元素具有类类型,将使用该类的默认构造函数实现初始化
    2. 如果数组元素是内置类型,则不会初始化,在数组长度后加一对空圆括号,对数组元素做初始化
    3. int * pia = new int[10]; //未初始化
      int * pia2 = new int[10](); //初始化为0
    4. C++不能定义长度为0的数组变量,但可以new动态创建长度为0的数组
    5. char arr[0]; //错误
      char * cp = new char[0]; //正确
    6. delete [] pia; 如果遗漏了空方括号,则会导致内存泄露(Memory Leak)
  6. C和C++代码混用:
    1. string s; const char * str = s.c_str(); (返回char*) 对s的操作可能会改变str,如果需要持续访问str,则应该复制str。
    2. int int_arr[5] = {1,2,3,4,5}; vector<int> ivec(int_arr, int_arr+5); vector用数组首地址和数组最后一个元素之后的那个地址来初始化一个vector
  7. 多维数组
      int * ip[4]; //array of pointers to int
      int (*ip)[4]; //pointer to an array of 4 ints