<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] ## 概述 指針的使用是現代編程中最容易出錯的領域之一,以至于像Java、C#和Visual Basic這些現代語言都沒有提供指針數據類型。 ## 用來理解指針的范例 從概念上看,每一個指針都包含兩個部分:內存中的某處位置,以及如何解釋該位置中的內容。 ### 內存中的位置 1. 內存中的一個位置就是一個地址,常用16進制形式表示。 2. 32位處理器中的一個地址用一個32位的值表示,比如0x0001EA40。 3. 指針本身只包含這個地址。為了使用該指針所指向的數據,就必須訪問該地址,解釋該位置的內存內容。 4. 如果去查看該地址的內存,可以發現它只是**一組二進制位**。必須經過解釋才能使它變得有意義 ### 如何解釋指針所指向的內容 1. 如何解釋內存中某個位置的內容,是由指針的基類型( base type)決定的。 2. 如果某指針指向整數,編譯器就會把該指針所指向內存位置的數據解釋為整數 3. **你可以讓一個整數指針、一個字符串指針和一個浮點數指針都指向同一個內存位置。但是其中(至多)只有一個指針能正確地解釋該位置的內容** #### 示例 在理解指針的時候,應該記住內存并不包含任何與之相關聯的內在的解釋。只有通過使用一個特定類型的指針,一個特殊位置的比特才能解釋為有意義的數據 * 原始內存空間 ``` [0A 61 62 63 64 65 67 68 69 6A] ``` 1. 解釋方式: String[10](以 Visual Basic的格式表示,第一個字節存儲長度) 意義:abcdefghij 2. 解釋方式:雙字節的整數 意義:24842 3. 解釋方式:雙字節的整數 意義:24842 4. 解釋方式:四字節的浮點數 意義:4.17595656202980E+0021 5. 解釋方式:四字節的整數 意義:1667391754 6.解釋方式:字符 意義:換行符(ASCI碼16進制的0A或者10進制的10) ## 使用指針的一般技巧 ### 把指針操作限制在子程序或者類里面 假設你在程序中多次使用了一個鏈表。每次使用它的時候,不要通過手動操作指針去遍歷該鏈表,應該編寫一組諸如 NextLink()、 PreviousLink()、 InsertIn()和 DeleteLink()這樣的訪問 ### 同時聲明和定義指針 在聲明處附近賦值 bad ``` Employee *empoyeePtr; // lots of code employeePtr = new Employee; ``` good ``` Employee *empoyeePtr = new Employee; ``` ### 在與指針分配相同的作用域中刪除指針 如果你需要在一個單一作用域內使用指針,那么就應該在此作用域范圍內用new分配指針,用 delete釋放指針。 如果你在一個子程序內分配了一個指針,那么就在同一個子程序里釋放它。 如果你在一個對象的構造函數里面分配了一個指針,就要在析構函數中釋放它 ### 用狗牌字段來檢測損壞的內存 是指你加入結構體內的一個僅僅用于檢測錯誤的字段。 在分配一個變量的時候把一個應該保持不變的數值放在它的標記字段里。當你使用該結構的時候---特別是當你釋放其內存的時---檢測這個標記字段的取值。 如果這個標記字段的取值與預期不相符,那么這一數據就被破壞了。 ### 按照正確的順序刪除鏈表中的指針 在使用動態分配鏈表時,經常遇到的個問題是,如果先釋放了鏈表中的第一個指針,就會致使表中的下一個指針無法訪問。為了避免這一問題,在釋放當前指針之前,要確保已經有指向鏈表中下個元素的指針。 ### 分配一片保留的內存后備區域 如果在你的程序中使用了動態內存,就需要避免發生程序忽然用盡了內存、把你的用戶和用戶的數據丟在RAM空間里的尷尬場景。 使你的程序對這類錯誤留出緩沖地帶的一種方法是預先分配一片內存后備區域。**設法確定程序為了“保存所做的工作,執行清理并體面地退出”需要用多少內存**。 在程序初始化階段把這部分內存分配出來作為后備,然后就可以不再管它。一旦你真的用光了內存,就釋放保留下來的這片后備區,執行清理工作然后退出 ### 粉碎垃圾數據 在C語言中,在釋放內存區域之前用垃圾數據來覆蓋這些內存區域,可以讓與使用已釋放的指針有關的錯誤的表現方式更一致。 在C++里面,你可以在每次刪除指針的時候使用類似于下面的代碼: ``` //強制讓釋放的內存包含垃圾數據 memset( pointer, GARBAGE_DATA, MemoryBlocksize( pointer )); delete pointer; ``` 對c++對象不奏效 ### 在刪除或釋放指針之后把他們設定為空值 可有效的防止"懸空指針" 盡管在刪除指針后再將其設為null并不能阻止你去讀取一個空懸指針所指向的數據,但這的確可以保證當你向一個空懸指針寫入數據時會產生錯誤。這一錯誤可能引發一場巨大的災難。但至少可以由你首先發現這一錯誤,而不是留給其他人。 example ``` //C++示例:在刪除指針之后將其設為NUL memset( pointer, GARBAGE_DATA, MemoryBlocksize( pointer )); delete pointer; pointer= NULL; ``` ### 在刪除變量之前檢測非法指針 通過斷言 ``` // C++示例:在刪除指針之前斷言其不為NULL ASSERT( pointer != NULL,"Atting to delete null pointer."); memset( pointer, GARBAGE_DATA, MemoryBlocksize( pointer )); delete pointer; pointer= NULL; ``` ### 跟蹤指針分配情況 維護一份你已經分配的指針的列表 ``` //G++示例:檢查是否已經分配了某個指針 ASSERT( pointer != NULL,"Atting to delete null pointer."); if (IsPointerInList(pointer)){ memset( pointer, GARBAGE_DATA, MemoryBlocksize( pointer )); RemovePointerPromList(pointer) delete pointer; pointer= NULL; }else{ ASSERT( FALSE, 'Attempt ing to delete unallocated pointer.): } ``` ### 通過子程序,集中實現上述所有策略 可以實現兩個子程序`SAFE_NEW`和`SAFE_DELETE` 1. SAFE_NEW 這個子程序調用new來分配指針 把這一新的指針加入已分配指針列表中, 然后將這一新分配的指針返回給調用方子程序。 它還可以在該子程序內檢查new操作的返回值是否為空或是否拋出異常(也就是是否發生“內存不足”錯誤),從而簡化了程序其他部分的錯誤處理。 2. SAFE_DELETE 這個子程序檢查傳遞給它的指針是否在已分配指針的列表里。 如果它在列表里,就把該指針所指向的內存設置為垃圾數值,把該指針從列表中移除,再調用C++的 delete運算符釋放該指針,并且把該指針設為空值。如果該指針不在列表里,那么SAFE_ DELETE將顯示一條診斷信息,并且終止程序運行。 ``` //C++示例:在刪除指針的代碼外加一層包裹 define SAFE_DELETE( pointer ){\ ASSERT( pointer ! NULL, "Attempting to delete null pointer. "):\ if (IsPointerInList( pointer )){ \ memset( pointer, GARBAGE_DATA, MemoryBlocksize( pointer )); \ RemovePointerPromList(pointer); \ delete pointer; \ pointer= NULL; \ else{\ ASSERT( FALSE, .Attempting to delete unallocated pointer .);\ } ``` ### 采用非指針的技術 采用非指針的技術指針比較難理解,容易用錯,也容易導致依賴于具體機器的不可移植代碼。如果你能想到任何替代指針的方案,而它又能工作得很合理,那么就應該去用它,避免這些令人頭痛的問題 ## C++ 指針 ### 理解指針和引用之間的區別 在C++中,指針(*)和引用(&)都能夠間接地引用對象。但事實上,最重要的區別是,引用必須總是引用一個對象,而指針則可以指向空值,還有,引用所指向的對象在該引用初始化之后不能改變 ### 把指針用于"按引用傳遞"參數,把 const引用用于"按值傳遞"參數 C++向子程序傳遞參數的默認方式是傳遞值( pass by value)而不是傳遞引用( pass byreference)。 當你以傳遞值的方式向一個子程序傳遞一個對象的時候,C++創建了該對象的一份拷貝,當該對象傳遞回調用方子程序的時候,又有創建了一份拷貝。 對于大對象而言,這種復制可能**耗費大量時間和其他的資源**。 因此,當你向一個子程序傳遞對象的時候,通常會希望避免復制該對象,這就意味著你希望按照引用來傳遞它而不是按值來傳遞。 ### 使用 auto_ptr 通過在離開作用域的時候自動釋放內存,auto_ptr(現在推薦使用 shared_ptr)能避免很多與常規指針相關的內存泄漏問題。 ### 靈活運用只能指針 靈活運用智能指針智能指針( smart pointers)是常規指針或者“啞(dumb)指針的一種替代品( Meyers1996)。它用起來與常規指針十分相像,但是針對資源管理、拷貝操作、賦值操作、對象構造和對象析構提供了更多的控制。 ## C指針 ### 使用顯式指針類型而不是默認類型 使用顯式指針類型而不是默認類型C允許你對任何類型的變量使用char或者void指針。C語言只關心這類指針有所指向,不會真正去關心它所指向的是什么。 然而,如果你使用了顯式的指針類型,編譯器就會針對不相符的指針類型和不合適的解除引用( dereferences)發出警告。 ### 避免強制類型轉換 強制類型轉換關閉了編譯器檢查類型不符的功能因此在你的防御式編程的鎧甲上挖了一個洞。 ### 遵循參數傳遞的星號規則 只有當你在賦值語句的參數前面加了星號(*),才能把該參數從子程序中傳回去。 ``` //C示例: 不奏效的參數傳遞 void TryToPassBackAvalue(int parameter){ paramter =SOME_VALUE; } //C示例:奏效的參數傳遞 void TryToPassBackAValue(int *paramter){ *paremter =SOME_VALUE; } ``` ### 在內存分配中使用 sizeof確定變量的大小 在內存分配中使用 確定變量的大小使用 sizeof()要比到手冊里去查找大小容易得多。 它是可以移植的—在不同的環境下重新編譯,將自動修改 sizeof()計算出來的值。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看