C++ 指針的算術運算
指針是一個用數值表示的位址。是以,您可以對指針執行算術運算。可以對指針進行四種算術運算:
++
、
--
、
+
、
-
。
假設
ptr
是一個指向位址
1000
的整型指針,是一個
32
位的整數,讓我們對該指針執行下列的算術運算:
在執行完上述的運算之後,
ptr
将指向位置
1004
,因為
ptr
每增加一次,它都将指向下一個整數位置,即目前位置往後移 4 個位元組。這個運算會在不影響記憶體位置中實際值的情況下,移動指針到下一個記憶體位置。如果
ptr
指向一個位址為
1000
的字元,上面的運算會導緻指針指向位置
1001
,因為下一個字元位置是在
1001
。
遞增一個指針
我們喜歡在程式中使用指針代替數組,因為變量指針可以遞增,而數組不能遞增,因為數組是一個常量指針。下面的程式遞增變量指針,以便順序通路數組中的每一個元素:
執行個體
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// 指針中的數組位址
ptr = var;
for (int i = 0; i < MAX; i++)
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// 移動到下一個位置
ptr++;
}
return 0;
}
當上面的代碼被編譯和執行時,它會産生下列結果:
Address of var[0] = 0xbfa088b0
Value of var[0] = 10
Address of var[1] = 0xbfa088b4
Value of var[1] = 100
Address of var[2] = 0xbfa088b8
Value of var[2] = 200
遞減一個指針
同樣地,對指針進行遞減運算,即把值減去其資料類型的位元組數,如下所示:
執行個體
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// 指針中最後一個元素的位址
ptr = &var[MAX-1];
for (int i = MAX; i > 0; i--)
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// 移動到下一個位置
ptr--;
}
return 0;
}
當上面的代碼被編譯和執行時,它會産生下列結果:
Address of var[3] = 0xbfdb70f8
Value of var[3] = 200
Address of var[2] = 0xbfdb70f4
Value of var[2] = 100
Address of var[1] = 0xbfdb70f0
Value of var[1] = 10
指針的比較
指針可以用關系運算符進行比較,如
==
、
<
和
>
。如果
p1
和
p2
指向兩個相關的變量,比如同一個數組中的不同元素,則可對
p1
和
p2
進行大小比較。
下面的程式修改了上面的執行個體,隻要變量指針所指向的位址小于或等于數組的最後一個元素的位址
&var[MAX - 1]
,則把變量指針進行遞增:
執行個體
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// 指針中第一個元素的位址
ptr = var;
int i = 0;
while ( ptr <= &var[MAX - 1] )
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// 指向上一個位置
ptr++;
i++;
}
return 0;
}
當上面的代碼被編譯和執行時,它會産生下列結果:
Address of var[0] = 0xbfce42d0
Value of var[0] = 10
Address of var[1] = 0xbfce42d4
Value of var[1] = 100
Address of var[2] = 0xbfce42d8
Value of var[2] = 200
#include <iostream>
using namespace std;
int main()
{
int var[5] = {1,2,3,4,5}; // 實際變量的聲明
int *ip;
// 指針變量的聲明
int *ip_1;
//ip = &var;
//指針指向數組的時候不用 “&”取址符
//ip = &var[2]
//指針指向數組某一進制素時要用 “&”取址符
ip = var;
// 在指針變量中存儲 var 的位址
ip_1 = &var[2];
// 在指針變量中存儲 var[2] 的位址
cout << "Value of var variable: ";
cout << var << endl;
// 輸出在指針變量中存儲的位址
cout << "Address stored in ip variable: ";
cout << ip << endl;
// 通路指針中位址的值
cout << "Value of *ip variable: ";
*ip = 30;
cout << *ip << endl;
cout << "\t" << var << endl;
// 列印指針指向數組的某一進制素的值
cout << "Value of *ip_1 variable:";
cout << *ip_1 << endl;
system("pause");
return 0;
}
& 并不是不能用在數組名上,隻是用在數組名和數組名
[i]
有所差別
int height[10];//int型的數組
cout << &height << endl;//&用在數組名上
cout << &height[0] << endl;//&用在數組第一個元素上
上面
&height[0]
就是取得是數組第一個元素的位址,假設位址為 1000;
&height
是直接對數組名進行取位址,這個時候就是取得是 height 整個數組的位址,指向包含 10 個元素的 int 型數組,位址範圍為 1000~1036;
我們知道
height
等價于
&height[0]
,
height+1
會将位址加 4 個位元組;但
&height+1
就是将位址增加 10*4 個位元組。
C++ 引用
引用變量是一個别名,也就是說,它是某個已存在變量的另一個名字。一旦把引用初始化為某個變量,就可以使用該引用名稱或變量名稱來指向變量。
C++ 引用 vs 指針
引用很容易與指針混淆,它們之間有三個主要的不同:
- 不存在空引用。引用必須連接配接到一塊合法的記憶體。
- 一旦引用被初始化為一個對象,就不能被指向到另一個對象。指針可以在任何時候指向到另一個對象。
- 引用必須在建立時被初始化。指針可以在任何時間被初始化。
C++ 中建立引用
試想變量名稱是變量附屬在記憶體位置中的标簽,您可以把引用當成是變量附屬在記憶體位置中的第二個标簽。是以,您可以通過原始變量名稱或引用來通路變量的内容。例如:
我們可以為 i 聲明引用變量,如下所示:
int& r = i;
double& s = d;
在這些聲明中,
&
讀作引用。是以,第一個聲明可以讀作 “r 是一個初始化為 i 的整型引用”,第二個聲明可以讀作 “s 是一個初始化為 d 的 double 型引用”。下面的執行個體使用了 int 和 double 引用:
執行個體
#include <iostream>
using namespace std;
int main ()
{
// 聲明簡單的變量
int i;
double d;
// 聲明引用變量
int& r = i;
double& s = d;
i = 5;
cout << "Value of i : " << i << endl;
cout << "Value of i reference : " << r << endl;
d = 11.7;
cout << "Value of d : " << d << endl;
cout << "Value of d reference : " << s << endl;
return 0;
}
當上面的代碼被編譯和執行時,它會産生下列結果:
Value of i : 5
Value of i reference : 5
Value of d : 11.7
Value of d reference : 11.7
int& r = i
; 和
int r = i
; 不同之處是記憶體的配置設定,後者會再開辟一個記憶體空間
#include <iostream>
using namespace std;
int main ()
{
int i;
int& r = i;
i = 5;
cout << "Value of i : " << i << endl;
cout << "Value of i reference : " << r << endl;
cout << "Addr of i: " << &i << endl;
cout << "Addr of r: " << &r << endl;
int x;
int y = x;
x = 6;
cout << "Value of x : " << x << endl;
cout << "Value of y : " << y << endl;
cout << "Addr of x: " << &x << endl;
cout << "Addr of y: " << &y << endl;
return 0;
}
輸出結果:
Value of i : 5
Value of i reference : 5
Addr of i: 0x7fff59cda988
Addr of r: 0x7fff59cda988
Value of x : 6
Value of y : 32767
Addr of x: 0x7fff59cda97c
Addr of y: 0x7fff59cda978
- 引用必須在聲明時将其初始化,不能先聲明後指派。
#include <iostream>
using namespace std;
int main()
{
int rats = 10;
//聲明引用,旦未初始化
int &rodents;
rodents = rats;
return 0;
}
上述代碼編譯時會報以下錯誤:
error: ‘rodents’ declared as reference but not initialized
錯誤:’
rodents
’ 聲明為引用但未初始化。
- 引用更接近
指針,必須在建立時進行初始化,一旦引用和某個變量關聯起來,該引用就會一直指向該變量。const
int rats = 10;
int &rodents = rats;
上面代碼實際上是下述代碼的僞裝表示:
int rats = 10;
int * const pr = &rats;
例子:
#include <iostream>
using namespace std;
int main()
{
int rats = 100;
int &rodent = rats;
cout << "rats = "<<rats<<", rosent = "<<rodent<<endl;
cout << "rats address = "<<&rats<<endl;
cout << "rosent address = "<<&rodent<<endl;
cout <<"==================================="<<endl;
int bunnies = 50;
rodent = bunnies;
cout << "rats = "<<rats<<", rosent = "<<rodent<<", bunnies = "<<bunnies<<endl;
cout << "rats address = "<<&rats<<endl;
cout << "rosent address = "<<&rodent<<endl;
cout << "bunniess address = "<<&bunnies<<endl;
return 0;
}
輸出結果:
rats = 100, rosent = 100
rats address = 0xbfce21e4
rosent address = 0xbfce21e4
===================================
rats = 50, rosent = 50, bunnies = 50
rats address = 0xbfce21e4
rosent address = 0xbfce21e4
bunniess address = 0xbfce21e8
從結果可以看出,雖然在調用
rodent = bunnies
; 後引用
rosent
的值變為 50,但是 rosent 所指向的位址空間還是指向了 rats,沒有發生改變,說明
rodent = bunnies
; 隻是将 bunnies 的值指派給引用 rodent 所指向的變量,沒有改變引用的指向。
C++ 把引用作為參數
下面的執行個體使用了引用來實作引用調用函數。
執行個體
#include <iostream>
using namespace std;
// 函數聲明
void swap(int& x, int& y);
int main ()
{
// 局部變量聲明
int a = 100;
int b = 200;
cout << "交換前,a 的值:" << a << endl;
cout << "交換前,b 的值:" << b << endl;
/* 調用函數來交換值 */
swap(a, b);
cout << "交換後,a 的值:" << a << endl;
cout << "交換後,b 的值:" << b << endl;
return 0;
}
// 函數定義
void swap(int& x, int& y)
{
int temp;
temp = x; /* 儲存位址 x 的值 */
x = y; /* 把 y 指派給 x */
y = temp; /* 把 x 指派給 y */
return;
}
當上面的代碼被編譯和執行時,它會産生下列結果:
交換前,a 的值: 100
交換前,b 的值: 200
交換後,a 的值: 200
交換後,b 的值: 100
引用作為函數參數
C++之是以增加引用類型, 主要是把它作為函數參數,以擴充函數傳遞資料的功能。
C++ 函數傳參:
- (1)将變量名作為實參和形參。這時傳給形參的是變量的值,傳遞是單向的。如果在執行函數期間形參的值發生變化,并不傳回給實參。因為在調用函數時,形參和實參不是同一個存儲單元。// 同 c
- (2) 傳遞變量的指針。形參是指針變量,實參是一個變量的位址,調用函數時,形參(指針變量)指向實參變量單元。這種通過形參指針可以改變實參的值。// 同 c
- (3) C++提供了傳遞變量的引用。形參是引用變量,和實參是一個變量,調用函數時,形參(引用變量)指向實參變量單元。這種通過形參引用可以改變實參的值。
以引用作為參數的函數,可以把變量傳入,但不能傳入常量。
#include <iostream>
using namespace std;
int hls(int& a1, int& a2, int& b1, int& b2) //定義行列式函數
{
int temp;
temp=a1*b2-a2*b1;
return temp;
}
int main()
{
int x1=11; int x2=9;
int y1=15; int y2=14; //定義矩陣
int result; //行列式運算結果
result=hls(x1,x2,y1,y2); //result=hls(11,9,15,14)會報錯
cout << result << endl;
return 0;
}