C++ 引用和指針
作者:AceTan,轉(zhuǎn)載請標明出處相艇!
引用和指針對于C++來說很重要椎麦,是學習C++繞不過去的一道坎。
引用
引用(reference) 就是給對象起別名暖璧。對引用的操作與對變量直接操作完全一樣。
這里說的引用泛指“左值引用(lvalue reference)”琳袄,C++11新增了一種引用江场,即所謂的“右值引用(rvalue reference)”,這里不作討論。
引用即別名窖逗,引用并非一個對象址否,不能定義引用的引用。
定義引用時碎紊,程序把引用和它的初始值進行綁定(bind)在一起佑附,而不是將初始值拷貝給引用。一旦初始化完成矮慕,引用和它的初始值對象一直是綁定在一起的,死也不分開啄骇。
舉個栗子:胡一菲的小名叫小菲菲痴鳄,那么對小菲菲的所有操作既是對胡一菲的操作。同樣缸夹,小菲菲這個名字就是胡一菲綁定在一起了痪寻。當然,胡一菲還可以有其他的別名虽惭,比如叫菲菲菲橡类。但需要注意的是,一旦有了這個小名芽唇,那么這個小名就不能指代其他人顾画。不然會死的很慘。
引用的定義
引用定義時就需要初始化匆笤。允許一條語句定義多個引用研侣,其中每個引用標示符都必須以符號&開頭。
int value = 1;
int &refValue = value; // refValue 指向value
int &refValue2; // 報錯炮捧,引用必須初始化
引用的寫法也還可以是這樣:
int value = 1;
int& refValue = value; // refValue 指向value
int& refValue2; // 報錯庶诡,引用必須初始化
注意&符號和int之間是否緊挨著,兩種寫法都是對的(下面介紹的指針也可以用這兩種寫法), 這個只是個人的代碼風格問題咆课,并無實質(zhì)差異末誓。
引用更為常見的用法應(yīng)該是作為函數(shù)的參數(shù),利用引用的特性书蚪,可以讓一個函數(shù)返回多個"返回值"喇澡。另外,當使用一個類作為函數(shù)參數(shù)時殊校,比較好的做法也是使用引用撩幽。這樣可以減少創(chuàng)建類副本的一些開銷。請看一個具體的示例:
#include <iostream>
using namespace std;
const double PI = 3.14;
// 圓的數(shù)據(jù)結(jié)構(gòu)
struct Circle
{
double radius; // 半徑
double circumference; // 周長
double square; // 面積
};
// 給出圓的半徑,計算圓的周長和面積窜醉,返回是否計算成功宪萄。
bool CalCirle(Circle& c)
{
// 給的圓的半徑為負數(shù),返回計算錯誤
if (c.radius <= 0)
{
return false;
}
// 周長的計算
c.circumference = 2 * PI * c.radius;
// 面積的計算
c.square = PI * c.radius * c.radius;
return true;
}
int main()
{
Circle c;
cout << "請輸入圓的半徑:";
cin >> c.radius;
if (CalCirle(c))
{
cout << "該圓的周長是" << c.circumference<< endl;
cout << "該圓的面積是" << c.square << endl;
}
else
{
cout << "您輸入的半徑不合法榨惰!" << endl;
}
return 0;
}
指針
指針(pointer) 是“指向(point to)”另外一種類型的復(fù)合類型拜英。
復(fù)合類型(compound type) 是指基于其他類型定義的類型。比較常見的是指針和引用琅催。
指針本身就是一個對象居凶,允許對指針的復(fù)制和拷貝,而且藤抡,在指針的生命周期內(nèi)侠碧,它可以先后指向幾個不同的對象。指針和其他變量一樣缠黍,定義的時候可以不賦值弄兜。如果指針未被初始化,那么它將擁有一個不確定的值瓷式。指針未初始化和空指針經(jīng)常引起程序崩潰替饿。
指針通常難以理解,即使是有經(jīng)驗的程序員也常常因為調(diào)試指針引發(fā)的bug而備受折磨贸典。
舉個栗子视卢,便于理解指針:指針好比門牌號,它所指向的是這個房間的東西廊驼,它本身也在有值的据过,它就是門牌上的號碼。你可以把門牌號取下來妒挎,掛在別的房間蝶俱,那么這個門牌號就指向了另一個房間。當然饥漫,你覺得有個門牌號不吉利榨呆,把它重新刷成其他門牌號,這樣也是允許的庸队。但你不能把兩個不同的房間都掛一樣的門牌號积蜻,那么別人就分不清了。某天你打開了某個房間(你需要鑰匙彻消,鑰匙就是解引用)竿拆,發(fā)現(xiàn)里面有個門牌號,這個就是多級指針宾尚。房間里的門牌號告訴你丙笋,你要找的東西在這個門牌號所指代的房間里谢澈。
指針存放某個對象的地址,要想獲得該地址御板,需要使用取地址運算符(操作符&)锥忿。
注意這里的取地址運算符&和聲明引用時標示符以符號&開頭的意義和用法是不一樣的。
int value = 2;
int* p = &value; // p存放變量value的地址怠肋,或者說p是指向變量value的指針
利用指針訪問對象:如果一個指針指向一個對象敬鬓,則允許解引用符(操作符*) 來訪問該對象。
int value = 2;
int* p = &value; // p存放變量value的地址笙各,或者說p是指向變量value的指針
*p = *p * 3; // 取這個變量钉答,并乘以3
cout << *p << endl; // 輸出結(jié)果為6
cout << value << endl; // 輸出結(jié)果為6
指針可以為空(引用是不可以的)¤厩溃空指針不指向任何對象数尿,一個良好的習慣就是使用指針前,一定要判斷是否為空惶楼。
得到空指針最直接的方法是用字面值nullptr 來初始化指針右蹦。(C++11引入的一種方法)
以前的方法是將指針初始化為字面值0或者NULL。(NULL為一個預(yù)處理變量鲫懒,它的值就是0)嫩实。
void* 指針 是一個特殊類型的指針,它可用于存放任意對象的地址刽辙。
指針的指針 指針級數(shù)是沒有限制的窥岩。但常見的也就是一級指針和二級指針,二級以上比較少見宰缤。給出一個多級指針的例子:
#include <iostream>
using namespace std;
int main()
{
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int b[3][4] =
{
11, 22, 33,
44, 55, 66,
77, 88, 99,
111, 222, 333
};
int *p1 = nullptr, *p2 = nullptr, **p3 = nullptr;
p1 = a; // p1指向a數(shù)組
p3 = &p1; // p3指向p1
for (int i = 0; i < 10; ++i)
{
cout << *(*p3 + i) << " "; // 輸出: 0 1 2 3 4 5 6 7 8 9
}
cout << endl;
for (p1 = a; p1 - a < 10; ++p1)
{
p3 = &p1;
cout << ** p3 << " "; // 輸出: 0 1 2 3 4 5 6 7 8 9
}
cout << endl;
for (int i = 0; i < 3; ++i)
{
p2 = b[i];
p3 = &p2;
for (int j = 0; j < 4; ++j)
{
cout << *(*p3 + j) << " "; // 輸出:11 22 33 44 55 66 77 88 99 111 222 333
}
}
return 0;
}
函數(shù)指針 是C++中最大優(yōu)點之一了颂翼。一般來說,使用函數(shù)指針比函數(shù)引用更為方便一些慨灭。
函數(shù)指針的聲明使用方式:
<想要指向的函數(shù)之 返回類型>(*函數(shù)指針的 名稱)<想要指向的函數(shù)之 參數(shù)類型…>
#include <iostream>
using namespace std;
void sayHello(const char* name)
{
cout << "Hello, " << name << endl;
}
int add(int a, int b)
{
return a + b;
}
int main()
{
void(*pFunc1)(const char*);
pFunc1 = &sayHello;
pFunc1("Ace Tan"); // 輸出:Hello, Ace Tan
int(*pFunc2)(int, int);
pFunc2 = &add;
cout << pFunc2(1, 2) << endl; // 輸出3
return 0;
}
函數(shù)指針也可以作為函數(shù)的參數(shù)朦乏,在這兒不做詳細介紹了。
總結(jié)
引用和指針有如下區(qū)別:
修改性:指針可以重新賦值以指向另一個對象氧骤。引用在初始化時就被綁定對象呻疹,以后無法改變。
非空性: 指針可為空筹陵,引用不可為空
傳遞性: 指針傳遞參數(shù)和值傳遞是一樣的刽锤,被當做局部函數(shù)來處理,不影響主調(diào)函數(shù)的實參變量朦佩。引用傳遞對形參的任何操作都影響了主調(diào)函數(shù)中的實參變量并思。
結(jié)束語
引用和指針在C++中應(yīng)用非常多,也非常靈活语稠。指針也是C++最難學的部分之一宋彼,少年弄砍,趕快去征服它吧。