PS,1880后程序員

          看不完的牙,寫不完的程序,跑不完的步。
          隨筆 - 97, 文章 - 34, 評論 - 10, 引用 - 0
          數據加載中……

          C++ Primer 之 讀書筆記 第四章

           

          第四章數組和指針

          Arrays and Points

          vectorarray類似的地方就是它們都是同一對象類型的集合。不同點是array是固定長度的。iterator之于vector就如同指針之于array

          使用指針的一個重要原因是vector不能提供所需的訪問速度。

          數組類型不能是引用(reference

          4.1 Array

          關于Array初始化:

          l         使用class默認的構造函數初始化每個單元。

          l         Character Array即可以用字符數組來初始化也可以用string來初始化,注意如果用string,那么自動在末尾追加了null作為結束符,這樣數組的長度+1.

          下標操作時,要使用數據類型是:size_t,就像在vector中使用size_type

          for (size_t ix = 0; ix != array_size; ++ix)

                              ia[ix] = ix;

          4.2 Pointers

          什么是指針

          Pointers are iterators for arrays.指針是用于數組的迭代器。

          pointer holds the address of another object:。具體來說,指針保存的是另一個對象的地址。

          string *sp = &s; // sp holds the address of s

          *sp里面*代表sp是一個指針。

          Best practice:指針初始化時,如果不能指向具體的地址,就設置為0,這樣在程序中就可以檢測出指針沒有指向一個對象(object)。

          指針初始化和賦值操作的約束

          指針初始化和賦值

          只有4類值可以初始化指針和指針賦值:

          1.值為0的常量表達式。不能把任何的int賦值給指針,即使這個int的值是0,但是可以把值是0const 或者數值0賦值給指針。NULL定義為0,所以也可以使用。NULL叫做預處理變量。

          int *pi = NULL

          2.類型匹配的對象的地址

          3.另一對象末的下一地址

          4.同類型的其它有效的指針

          void*指針,這是一個特殊類型的指針,它能夠是任何對象的地址。它就是說明它的值是一個指針,但是指針所指向的對象的類型是不可知的。

          因此void*指針只能執行通用的操作:

          l         指針比較

          l         傳遞給function或者作為function的返回值。

          l         賦值給另一個void*指針

          Operations on Pointer(指針操作)

          注意*在這里是一個operatordereference a pointer。解引用操作(dereference operator)返回指定對象的左值lvalue。因此可以進行賦值操作。

          引用和指針的區別:

          1.        引用總是指向對象object。引用必須初始化,但指針是可以僅僅定義,而無需初始化的。

          2.        賦值:引用的賦值會改變引用所綁定的對象的值;引用是不能重新綁定新的對象的。一旦初始化,引用總是指向同一個對象。

          引用:

          int &ri = ival, &ri2 = ival2;

          ri = ri2;    // assigns ival2 to ival這里riri2還是指向2個不同的地址單元

          指針:

          int ival = 1024, ival2 = 2048;

          int *pi = &ival, *pi2 = &ival2;

          pi = pi2;    // pi now points to ival2pipi2都指向了同一個地址單元

          指向指針的指針**ppi,代碼:

          int ival=1024;

          int *pi = &ival;

          int **ppi=π

          int *pi2 =*ppi; //或者 int *pi2 = pi;

          ppi解引用2次,就可以得到ival的值了。

          1.        使用指針訪問數組單元

          當使用數組的名字時,這個名字就自動轉換為指向數組第一個單元的指針。

          int ia[] = {0,2,4,6,8};

          int *ip = ia; // ip points to ia[0] 定義ip是指針,賦值為ia

          指針的算數運算會產生一個新指針。

          兩指針相減得到的數據類型是ptrdiff_t。它是一個

          int last = *(ia + 4); // ok: initializes last to 8, the value of ia[4]

          如何獲得一個數組的結尾?

          const size_t arr_size = 5;

          int arr[arr_size] = {1,2,3,4,5};

          int *p = arr;           // ok: p points to arr[0]

          int *p2 = p + arr_size; // ok: p2 points one past the end of arr

          p2就是指向了數組的結尾。

          指向const對象的指針和const指針

          1.        指向const對象的指針

          如果指針指向的是一個const對象,那么肯定不希望它能夠修改這個const對象的值。那么這樣的指針如何定義?

          const double *cptr; //cptr是指向const double類型的指針

          對于這個定義的理解是這樣子的:

          A.        這里的限定詞(qualifier-const是限定cptr指向的數據類型必須是const double,而不是限定cptr本身。

          B.        cptr本身不是const

          C.       不能做的是用cptr去修改它指向的對象的值

          但是也可以把指向const對象的指針賦值為非const對象的地址。(A pointer to a const object can be assigned the address of a nonconst object

          int val=10;

          const int *cptr = &val;

          val=30;   //這樣寫是對的

          *cptr = 30; //這樣寫會死人的L

          不過我想,這只不過是代碼上的文字游戲而已,如果程序這樣寫,也許會死人的。混亂!

          這種指針的用途是作為方法的參數,這可以保證這個參數不會在方法中被修改。(哎,要不怎么說是大師呢,佩服!)

          2.        const指針

          const指針的值是不可以修改的,但是const指針指向的對象的值是可以修改的。

          int errNumb = 0;

          int *const curErr = &errNumb; // curErr is a constant pointer

          *curErr = 0; // ok: reset value of the object to which curErr is bound

          3.        指針和typedef

          復習:

          typedef 可以用來定義類型的同義詞。wages就是double的同義詞

          typedef double wages;       // wages is a synonym for double

          (以下的這段很饒人啊)

          typedef string *pstring; //pstringstring的同義詞;并且pstring是指針類型

          const pstring cstr; //這是指向stringconst指針,而不是指向const string的指針

          第一繞:pstring類型是指向string類型的指針類型。

          第二繞:const是用來修飾pstring類型的,const pstring就是conststring指針

          第三繞:這不存在簡單的文字替換的游戲:const pstring cstr;等于const string* cstr;所以就是指向const string的指針。錯誤!

          4.3 C風格字符串

          不建議在C++中使用C風格的字符串,原因是它有“many many”的安全問題。

          1.        什么是C風格的字符串?

          它不是一種類型,而是以空字符 null 結束的字符數組。

          定義:

          char ca2[] = {'C', '+', '+', '"0'}; // explicit null

          char ca3[] = "C++";     // null terminator added automatically

          const char *cp = "C++"; // null terminator added automatically

          char *cp2 = ca2;   // points to first element of a null-terminated char array

          遍歷字符串

          const char *cp = "some value";

          while (*cp) {

              // do something to *cp

              ++cp;

          }

          2.        字符串函數

          C標準庫提供了一系列的字符串函數,但是這些函數都不檢查參數的合法性(限制條件)。這就是Lippman不建議在C++中使用C風格的字符串的原因。

          主要的限制:

          1.        傳遞給這些標準庫函數的指針必須是非空的。

          2.        每個指針必須是以null結尾的。

          3.        數組的長度要足夠大

          strlen(s),返回的是s的長度,但是這里并不包含null,因此數組的實際長度是strlen(s)+1

          3.        使用動態數組

          為什么要使用動態數組?

          通常是因為在編譯時無法知道數組的維數,所以才需要動態創建該數組。

          size_t n = get_size(); // get_size returns number of elements needed

          int* p = new int[n];

          如果是普通的定義數組,以上的定義是根本無法實現的,因為在編譯期是不能確定數組的大小的。只能這樣定義:

          const n=45;

          int p[n];

          因此就可以得出結論:動態數組主要是用于當數組的尺寸不能在編譯期確定的情況。

          數組釋放:

          delete [] p ;

          4.        疑問代碼(P139):

          我認為在const size_t len = strlen(pc +1);  這行存在筆誤,應該是

          const size_t len = strlen(pc )+1;

          否則copy后得到的結果pc2不是C風格的字符串,因為最后一個單元的內容是’g’而不是null

          const char *pc = "a very long literal string";

           const size_t len = strlen(pc +1);     // space to

           // performance test on string allocation and copy

           for (size_t ix = 0; ix != 1; ++ix) {

               char *pc2 = new char[len + 1]; // allocate the space

               strcpy(pc2, pc);               // do the copy

               cout << "pc2=" << pc2 << endl;

               cout << "pc2[25]=" << (pc2+25) << endl;

               delete [] pc2;                 // free the memory

           }

          4.4多維數組 Multidimensioned Arrays

          C++實際是沒有多維數組的,

          int ia[3][4]

          可以理解為數字大小是3,每個單元element又是一個大小是4int數組。或者叫做33列。

          1.        指針和多維數組

          這段代碼就如同“回”字的N多種寫法一樣:

                 int ia[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

                 //*ip是一個指針變量,它指向的是長度是4int數組。

                 int (*ip)[4]=ia;

                 //*ipo是一個指針數組

                 int *ipo[4] ;

                 ipo[2]=ia[2]; //對指針數組的單元賦值

                 //*ipt就是一個最普通的指針,對指針變量賦值

                 int *ipt=ia[2];

                 //

                 int (*ipn)[4]=ia;

                 ipn=&ia[2]; //也可以寫為ia+2

                

                 cout << "(*(ip+2))[0]=" << (*(ip+2))[0] << endl;

                 cout << "ipo[2][0]=" << ipo[2][0] << endl;

                 cout << "ipt[0]=" << ipt[0] << endl;

                 cout << "(*ipn)[0]=" << (*ipn)[0] << endl;

          打印結果是一樣的,都是‘8’。

          2.        以下2種定義的區別(圓括號是必不可少的)

          指針數組:

           int *ip[4]; // array of pointers to int

          如果從內向外閱讀 ip 的聲明,則可理解為:*ip int[4] 類型——即 ip 是一個指向含有 4 個元素的數組的指針。

           int (*ip)[4]; // pointer to an array of 4 ints

          進一步的理解:

          int (*ip)[4]=ia;

          ip=&ia[2]; //也可以寫為ia+2

          剛開始,我覺得應該寫成ip=ia[2];結果得到報錯信息:

          error: cannot convert `int[4]' to `int (*)[4]' in assignment

          因為ia[2]就是一個數組啊,再想如果這樣寫ip=ia[2];這就相當于

          int ia[4]= {0,1,2,3};

          int *ip=ia;

          ip=ia[2];

          當然是錯誤的。

          posted on 2009-05-06 09:59 amenglai 閱讀(272) 評論(0)  編輯  收藏 所屬分類: C++ Primer 之 讀書筆記

          主站蜘蛛池模板: 华蓥市| 大姚县| 洛浦县| 武义县| 海兴县| 泰来县| 水富县| 泰宁县| 信宜市| 客服| 西盟| 南安市| 如皋市| 聊城市| 老河口市| 衡水市| 大庆市| 汾西县| 苗栗县| 习水县| 奉化市| 邮箱| 阳西县| 濉溪县| 互助| 内乡县| 乌鲁木齐县| 和田县| 苍南县| 长武县| 福清市| 贞丰县| 大化| 安远县| 安化县| 德令哈市| 南阳市| 贵港市| 理塘县| 德阳市| 满洲里市|