c++中的復合類型


  復合類型是指基於其他類型而定義的類型。 而這里介紹的是引用和指針。並且指針和引用都提供了對其他對象的間接訪問。

  

引用

  引用還是很好理解的,就是為對象起了另外一個名字,引用類型引用另外一種類型。 通常將聲明符協程 &d 的形式來定義引用類型,其中d是聲明的變量名。   

  注意:引用不是對象。 

  一般,在初始化變量時,如int a = 3; int b = a; 這時,這里b的初始化就會將a的值拷貝到新建的對象中。即int b = 3這里新建了一個對象來存儲,對a和b的操作是獨立的。 而定義引用時,程序會把引用和他的初始值綁定在一起,而不是將初始值拷貝給引用。如下所示:

#include <iostream>
using namespace std;
int main()
{
    cout << "beginning!" << endl;
    int a = 2;
    int &b = a;
    cout << "b的值為:" << b << endl; // 2
    b = 5;
    cout << "a的值為:" << a << "\t b的值為:" << b << endl; // a 和 b都是5
    return 0;
}

  如上,我們可以看到:b就是a的引用,這里b的值也是2,所以引用就是給a了一個別名b,並且並沒有給b一個新的對象,而是將b和a綁定在了一起,我們修改b的值,發現a和b的值同時修改成了5,這就是引用。 

  那么引用的目的是怎樣的呢? 一般來說,引用比指針更容易操作、也更不容易出錯。可以代替指針。

  需要注意的:

  • 引用必須賦初值。
  • 引用和之前的類型要嚴格匹配。
  • 如上的int &b 是指引用類型b是指向int類型的引用。 

 

 

 

指針

  指針是指向另外一種類型的復合類型。

  指針如果要指向某個對象,是存放着某個對象的地址。 如下:

    int a = 10;
    int *p = &a;
    cout << &a << endl;

  其中&a就是獲取a的地址。  int *p是指p是一個指向int類型對象的指針。 

  以上,我們已經定義了指針,那么如何利用指針訪問它所指的對象呢? 使用 * 解引用符即可。 

    int a = 10;
    int *p = &a;
    cout << *p << endl; // 10

  如上所示: 我們可以得到 *p 的值為10。 

  

  注意: 某些符號具有多重含義!這里講解 * 和 &。 

  int i = 42;

  int &r = i;  // &緊隨類型名出現,這里的&為引用。 

  int *p; // *緊隨類型名出現,這里的 * 為定義指針類型的p。  

  p = &i; // 這里的&出現在表達式中,是一個取地址符。

  *p = i; // 這里的 * 出現在表達式中,是一個解引用符。 

  int &r2 = *p; // 這里的 * 出現在表達式中,是一個解引用符。 

  

  

空指針

  即Null pointer,它是不指向任何對象的,一般我們建議:初始化所有的指針,並且在可能的情況下,盡量等定義了對象之后在定義指向他的指針,如果不清楚它指向何處,就初始化為空指針。

  定義空指針一般有三種方法,如下所示:

#include <iostream>
#include <cstdlib>
using namespace std;
void IsNull(int *p);
int main()
{
    cout << "beginning!" << endl;
    int *p = 0;
    IsNull(p);
    int *p1 = nullptr;
    IsNull(p1);
    int *p2 = NULL;
    IsNull(p2);
    int a = 5, *p3 = &a;
    IsNull(p3);
    return 0;
}
void IsNull(int *p)
{
    if (p == nullptr)
    {
        cout << "空指針" << endl;
    }
    else
    {
        cout << "非空指針" << endl;
    }
}

  三種方法為賦值為0、賦值為NULL、賦值為 nullptr,最后一種方法是c++11所新定義的,也是我們推薦的,在判斷一個指針是否為空指針時,我們只需要判斷其是否與nullptr相等即可。 注意:NULL的值就是0,是在 cstdlib 庫中定義的。

  注意:如果指針沒有初始化為空指針或者指向明確的對象,那么很有可能會導致整個程序的崩潰,並且難以入手解決問題。

 

 

    int i = 42;
    int *pi = 0; // 定義pi為空指針
    int *pi2 = &i; // pi2指向i
    cout << *pi2 << endl;
    int *pi3;

    pi3 = pi2; // 注意:這里並不是Pi3指向pi2,而是pi3指向了和pi2相同的對象,即這時pi3同樣指向i。 
    pi2 = 0;
    cout << *pi3; // 42
    cout << *pi2; // 報錯

 

另外,如果指針指向為空,則if判斷時的結果為false,且指針之間可以使用 == 來判斷是否相等,比如指向同一個對象、都為空等等。

 

注意: void*指針可以存放任何類型的對象,不受限制,但利用也比較有限。 

  

 

總結

  指針和引用都提供了訪問對象的其他方法,但為什么c++中同時有指針和引用呢? 如下:

可以看到,在第一個例子中,顯然使用引用更加舒服一些。 另外,我們怎么理解這種參數的使用方式呢,實際,f1要求的兩個指針,比如f1在調用時是f1(p1, p2),即const complex * x = p1。 因為p1是指針,可以直接賦值。 

 

 

指向指針的指針  

  

        int i = 42;
	int *p1 = &i;
	int *p2 = nullptr;
	p2 = p1;
	cout << *p2; //42

如上所示,p2 = p1的意思是p2指針指向p1指針所指向的對象,而不是p2指向p1,那么如何定義p2指向p1,即指向指針的指針呢?

 

    int i = 42;
    int *p1 = &i;
    int **p2 = &p1;
    cout << **p2; //42

如上所示: p2就是一個指向指針的指針。 

 

指向指針的引用

  指針是對象,所以可以有指向指針的引用,如下:

    int i = 42;
    int *p1 = &i;
    int  *&r = p1; // 這里的r就是指向指針的引用
    *r = 365;
    cout << *r;  //365

  如上所示:p1是指向int型變量i的指針,而 r 是指向指針型變量的引用,即我們對r的操作就是對p1的操作,因此,我們可以得到最后的結果為365。 

 

 

 

 

 

參考鏈接:http://www.stroustrup.com/bs_faq2.html#pointers-and-references


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM