<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    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=&pi;

    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 閱讀(268) 評論(0)  編輯  收藏 所屬分類: C++ Primer 之 讀書筆記

    主站蜘蛛池模板: 亚洲国产美女视频| 亚洲AV无码成人网站久久精品大| 久久精品乱子伦免费| 亚洲午夜无码片在线观看影院猛| 亚洲日本一区二区| 免费人成在线观看网站| 国产亚洲综合一区柠檬导航| 久久免费香蕉视频| 亚洲AV无码一区东京热| 182tv免费观看在线视频| 国产成人精品日本亚洲专区| 国产VA免费精品高清在线| 永久免费毛片手机版在线看| 亚洲人成无码网站在线观看 | 中文字幕亚洲免费无线观看日本| 三级黄色免费观看| 亚洲av无码专区国产乱码在线观看| a国产成人免费视频| 亚洲V无码一区二区三区四区观看| 免费精品无码AV片在线观看| 亚洲午夜电影在线观看高清 | 日本中文一区二区三区亚洲| 一区二区三区在线免费| 日本高清免费不卡视频| 国产亚洲精品美女久久久久| 最近2019中文字幕mv免费看| 亚洲av激情无码专区在线播放 | 男人j进入女人j内部免费网站| 亚洲自偷自偷精品| 免费看美女被靠到爽的视频| 91av免费在线视频| 亚洲乱码卡一卡二卡三| 国产免费牲交视频| 亚洲高清国产拍精品熟女| 免费观看成人毛片a片2008| 亚洲国产精品成人综合色在线| 国产亚洲精品自在线观看| 中文字幕无码播放免费| 日韩在线视频免费| 亚洲人成人无码网www国产| 美女被吸屁股免费网站|