指針和引用html
區別數組
>引用在建立的時候須要初始化, 指向有效對象, 必須與合法的存儲單元關聯, 不能再改變爲其餘對象的引用;函數
>指針能夠在定義之後任意時候再初始化, 指向的地址和地址內存放的數據均可以改變;spa
>引用不可爲空, 指針能夠爲空 (0/NULL);翻譯
>const指針能夠是NULL, 也有多是野指針;
指針
>引用和指針的語義是類似的, 引用是不可改變的指針, 指針是能夠改變的引用. 其實都是實現了引用語義. htm
常引用 對象
>利用引用提升效率 保護數據不被改變 const [type]& [name] = var; blog
Note 用基類指針操做派生類的數組, p++不是指向下一個元素, 而是指向了一個不合適的內存地址(類型不一樣); void* p; 不能++; 內存
---End---
函數傳參
傳值
>函數內會爲形參開闢一個新的內存空間存放實參的值, 是實參的副本;
>指針是個存放地址的變量,傳遞指針參數本質上是值傳遞, 傳遞的是內存地址, 固定大小(一個pointer, 通常爲4);
>若是函數的形參爲字符串指針, 那傳遞的是地址值, 在函數內部修改形參的值並不能真正的改變傳入實參的值;
void GetMemory( char* p ) { //改變了做爲形參的指針的地址變量, 不會對實參有影響; p = (char*) malloc( 100 ); }
>p[]數組爲函數內的局部自動變量, 棧內存在函數返回後內存已經被釋放;
char* GetMemory( void) { char p[] = "hello world"; return p; }
傳指針
>若是是修改指針指向的地址存放的值, 這樣能夠改變實參的值;
void GetN(int* n) { *n = 3; }
>要改變指針指向的地址, 使用指針的指針, 或者指針的引用;
void GetMemory( char** p, int num ) { //這裏須要判斷是否申請成功 if(*p == NULL), 須要釋放free; *p = (char*) malloc( num ); }
傳引用
>引用是內存別名, 定義須要初始化, 存在依附性, 地址不可改變;
void GetMemory( char* &p, int num ) { p = (char*) malloc( num ); }
>引用傳遞中, 函數的形參雖然也做爲局部變量在棧中開闢了內存空間, 可是存放的是函數傳遞進來的實參的地址; 對形參的操做會被處理成間接尋址(經過棧中存放的地址訪問實參的數據變量).
>引用不產生對象副本(不會調用構造), 參數傳遞時不須要複製對象, 提升效率;
>若是函數返回了引用, 那麼函數的調用也能夠被賦值;
double &max(double &d1,double &d2) { return d1>d2?d1:d2; } //--- max(x,y)+=1.0;
<refer to> http://xinklabi.iteye.com/blog/653643
---End---
指針數組和數組指針
指針數組-存儲指針的數組; int* p[n]: 聲明瞭一個數組, 數組的元素是n個int型的指針;
[]的優先級比*高, p和[]先結合成爲數組; p是指向數組首地址的指針; [原文說p是個不可知的表示]
[原文說:執行p+1是錯誤的, 但(p+1)就是指向p[1]的指針, 就是指向數組元素(int指針)的指針)]
>指針數組是多個指針變量, 以數組的形式存放在內存中, 佔有n個指針的存儲空間;
>二維數組賦給指針數組:
int *p[3];//數組存放了3個指針變量 p[0]~p[2] int a[3][4]; for(i=0;i<3;i++){ p[i]=a[i]; }
表示數組中i行j列的元素的方式: *(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]
數組指針-指向數組的指針; int (*p)[n]: 聲明瞭一個指針, 指向一個擁有n個int元素的數組;
()的優先級高, p和*結合成爲指針; 這個一維數組的指針也稱爲行指針, p+1時, p會跨過n整個整型數據的長度(步長), 也就是跨過數組;
>數組指針是一個指針變量, C語言中用來指向二維數組, 內存中只佔一個指針的存儲空間;
Class **Menu = new Menu*[NUM]; //指針指向數組, 數組的內容是指針, 即: 指針數組的數組指針...
>二維數組賦給數組指針:
int a[3][4]; int (*p)[4]; //該語句是定義一個數組指針,指向含4個元素的一維數組。 p=a; //將該二維數組的首地址賦給p,也就是a[0]或&a[0][0] p++; //該語句執行事後,也就是p=p+1;p跨過行a[0][]指向了行a[1][]
<refer to> http://www.cnblogs.com/hongcha717/archive/2010/10/24/1859780.html
指針和數組
char str[] = "world"; cout <<str<<" "<< sizeof(str) << ": "; char* p = str; cout <<p<<" "<<sizeof(p) << ": ";
>str是數組名, 編譯器經過數組名查到數組大小, str是C風格的字符串, 長度須要加上一個\0;
>p是指針, 長度爲一個地址, 大小不變, 通常狀況下, 32位是4, 64位是8;
>不變的還有char, 佔一個機器字節;
---End---
常量指針和指針常量
>常量指針- 指向常量的指針; 指針指向的內容不可修改, 指針自身的地址值可變;
const在*左邊: const char* ptr; 或 char const* ptr; 讀做: pointer to const char: 指向const char的指針; (內容不變)
>指針常量- 指針是一個常量; 指針內存儲的地址值不可變, 指向的數據內容可修改;
const在*右邊: char* const ptr; 讀做: const pointer to char: const指針, 指向char; (地址不變)
[中文翻譯坑爹, 用英文理解就很清晰, 中文應該記成: 常量的指針, 指針是常量]
int a = 1; int b = 2; int* pa = &a; int* const* pointerToConstPointer = &pa; int* pb = &b; pointerToConstPointer = &pb; *pointerToConstPointer = pb; //error **pointerToConstPointer = 10;
>對於模板形式有點不一樣:
//1 std::vector<int>::const_iterator Iter = vec.begin(); //內容是const的 *Iter = 10;//錯誤,Iter是常量指針 Iter++;//正確,Iter自己可變 //2 const std::vector<int>::iterator Iter = vec.begin(); //地址是const的 *Iter = 10; //正確,指針常量 Iter++; //錯誤,指針自己不可變
<refer to> http://www.cnblogs.com/xfxsworld/archive/2008/01/30/1059303.html & http://www.gocalf.com/blog/cpp-const-and-pointer.html
---End---
OTHER
重載運算符不能對指針單獨操做
>由於系統已經定義了兩個指針的運算, 你不能改變它; e.g. 兩個同類型的指針相加, 就是地址相加, 若是編譯器未定義就是無心義的;
Note 指針之間能夠相減, 但不能夠相加: 兩個同一類型的指針變量是能夠相減的, 他們的意義表示兩個指針指向的內存位置之間相隔多少個元素(注意是元素, 並非字節數) 例如對於int類型的指針p和p1. p1-p的意義表示他們之間相隔多少個int類型的元素. 一樣對於其餘類型的指針變量之間相減的意義也是同樣.
>運算符重載參數必須至少有一個類類型的形參;
friend Test operator * (const Test &src1, const Test *src2) //ok friend Test operator * (const Test *src1, const Test *src2)//error
---End---