指針和引用(整理)

指針和引用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---

相關文章
相關標籤/搜索