開原始碼分析的一些筆記

來源:互聯網
上載者:User

聲明與定義分離
標頭檔:用於記錄聲明代碼
模組檔案(c檔案/cpp檔案):用於記錄實現代碼

 

絕大多數串連程式是把一個模組中的所有函數、變數當作整體串連到執行程式中。
只要引用了模組中的一個名字,整個模組就進入執行檔案(如果模組10M,則所有引用過這個模組的執行檔案都要超過10M)

多個函數的實現,應該分到不同的模組
     可(但不一定)放在一個模組的函數
           相互調用的函數
          一定會被同時調用的函數
                open()/close(), new/delete
          非常相關的函數
     不可放在一個模組的函數
           不相關的函數
如果不知道如何做,則每個模組只放一個函數

 

聲明與標頭檔
       不能把所有聲明放到一個標頭檔
            主要是維護的問題
            相關的函數放在一個標頭檔
            不相關的函數放在不同的標頭檔
    如果不知道如何做,每個模組對應一個標頭檔

 

使用#ifndef...#define...#endif語句可以防止標頭檔被多次包含。

對象
      對象的實體被定義時,應初始化成確定狀態
              避免在非確定狀態對對象進行操作
              可能導致難以預料的錯誤
     對象死亡時,應清除所有可能的影響
             避免對系統造成不可恢複的影響
             資源泄漏

對應的就是類的建構函式和解構函式。

 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`

 

與記憶體相關的內容:

 

變數(variable)有不同類型,可能佔據不同數量的記憶體單元。但是一個變數佔據的記憶體單元總是連續的。

變數的地址(variable address)給變數分配的記憶體單元中最小的地址,又叫做“首地址”。

數組:記憶體中的分布,連續的多個記憶體單元。

記憶體是寶貴的資源,不能浪費!
自動(auto)變數:編譯器在需要的地方自動插入分配和釋放相應記憶體單元的指令,無需程式員管理。

棧(stack):管理函數調用和返回資訊,管理自動變數,空間比較小,32位平台上,一般1MB左右。
堆(heap):現代電腦的記憶體空間是比較大的,32位平台:最多4GB,棧只佔用很小一部分:1MB,一般通過new操作符分配的記憶體都屬於堆。

 

指標的大小通常和整數的大小相同,32位平台,通常是32位,或4位元組,與指標所指向的內容的大小無關。

指標指向內容的範圍:由程式員控制,不再使用的時候,要釋放。如果忘記釋放,就會產生記憶體泄露;如果尚未分配記憶體就訪問其指向的內容:非法指標訪問。如果訪問的單元超出了分配的範圍:指標越界。

 

對指標操作的一些建議:

總是把指標初始化成空NULL。

用C++類防止記憶體流失:
建構函式:在定義變數的一開始被自動調用
解構函式:在變數被釋放前被自動調用

 

 

class TCharArray
{
public:
 char *img;                          //要管理的記憶體
 int     len;                           //分配的記憶體大小
 TCharArray()
 {
  img = NULL;                      //初始化為空白狀態
  len  = 0;
 }
 ……

~TCharArray()                     //解構函式
 {
  Close();                            //調用記憶體釋放函數(很重要!)
 }
 void Close()
 {
  if(img!=NULL)                    //測試是否已經分配
  {
   delete []img;                    //如果是,則釋放,並恢複成空狀態
   img = NULL;
   len  = 0;
  }
 }
 ……

void Alloc(int size)                //記憶體配置函數
 {
  Close();                             //用記憶體釋放函數(很重要!)
  img = new char[size];       //分配記憶體,設定成合法狀態
  len  = size;
 }
 ……

char operator[](int inx)        //定義operator[]操作符重載函數,只能夠讀取資料對象的傳回值,不能實現在client代碼中做修改
 {

  assert( (i>=0) && (i<len) );
  return img[inx];
 }

 

char &operator[](int inx)      //返回引用,這樣就可以在client代碼中,直接對TcharArray類的資料對象就可以直接修改了。
 {
  assert( (i>=0) && (i<len) );
  return img[inx];
 }

};

下面是一個小例子,把上面的想法都實現了一下:

 

#include<iostream>
#include<cassert>
#include<string>
using namespace std;

template<typename T>     //類模板
class Array{
 
public :
 
 Array(){
  
  len=0;
  intPointer=NULL;
 }
 
 void allocate(int size){
  
  deAllocate();
  len=size;
  intPointer=new T[size];
  memset(intPointer,0,size*sizeof(T)); //初始化
  
 }
 
// int operator[](int pos){  //重載operator[],這樣可以直接通過Array[]形式訪問元素
//  
//  assert((pos>=0) && (pos<len));
//  return intPointer[pos];
// }
 
 int& operator[](int pos){  //重載operator[],返回引用,這樣就可以直接修改資料對象的值了
  
  assert((pos>=0) && (pos<len));
  return intPointer[pos];
 }
 
 ~Array(){
  
  deAllocate();    //釋放對象佔用的記憶體空間
 }

private:

 void deAllocate(){
  
  if( intPointer!=NULL){
   
   delete [] intPointer;      //delete [] intPointer是通用的
   len=0;
   intPointer=NULL;
  }
 }
 int len;
 T *intPointer;
 
};

template<class T>     //模板函數
void exchange(T& t,T& s){
 
 T tmp=s;
 s=t;
 t=tmp;
}

int main(){
 
 Array<int> a;
 a.allocate(5) ;
 cout<<a[1]<<endl;

//直接使用[]操作符,並就行修改,如果沒有對operator[]返回引用值的版本進行重載,就會出現:

//[Error] C:/Users/Administrator/Desktop/test.cpp:73: error: non-lvalue in assignment
 a[1]=8;                               

 cout<<a[1]<<endl;
 
 int c=4,d=5;
 exchange(c,d) ;

//輸出5 4
 cout<<c<<" "<<d<<" "<<endl;  
 
 return 0;
}

volatile: 如一個變數可能被多個線程修改,應定義為volatile
this: C++成員函數中指向當前對象的指標

全域變數:程式的整個生存周期都存在,常量和全域資源的管理資料

靜態變數:程式的整個生存周期記憶體在,當函數被遞迴調用時,也僅有一個變數。注意靜態變數和全域變數都是一樣的,在程式的整個生命週期中都存在。

 

棧:管理函數調用和返回,分配局部變數,不能返回指向局部變數的指標或引用!

棧:
一般不太大(1MB或以下)
大塊的記憶體應該程式員主動管理,不應自動管理
不要定義大的局部數組
堆:
程式員主動管理的記憶體
主要的儲存資源

 

使用堆時要注意的一些地方:

盡量用sizeof計算變數的大小,特別是結構的大小,結構的大小在不同的編譯選項下面可能有差異。

 

void * 類型: 可以指向任何類型的指標
const:

1、不可改變的量可以被定義為常量,以防止非正常修改變數的值,並且提供編譯最佳化的可能性
2、不應改變的函數參數,主要是指標和引用

3、常量指標和指向常量的指標:

常量指標:指標本身不可改變
char * const FileName;
FileName[0] = 0; (對)
FileName = newFileName; (錯)
指向常量的指標:指標可改變,但內容不可改變
const char * FileName;
FileName[0] = 0; (錯)
FileName = newFileName; (對)

4、常成員函數:不修改類變數的函數

 

           

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.