天天看點

C++ 指針的算術運算、指針和數組、引用

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
           
  1. 引用必須在聲明時将其初始化,不能先聲明後指派。
#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

’ 聲明為引用但未初始化。

  1. 引用更接近

    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;
}
           

繼續閱讀