指標的引用——在函數中的巧妙應用,指標引用函數

來源:互聯網
上載者:User

指標的引用——在函數中的巧妙應用,指標引用函數


前面有一篇文章講了指標與引用。並且還提到不能定義指向引用的指標(因為引用不是對象,沒有實際的地址)。那麼,能否定義指標的引用呢?答案是肯定的,因為指標本身就是一個對象。即然是對象,就能定義一個引用邦定該對象。先來看看指標的引用的用法:

 

以int類型為例如下:

void ReferencePointer(){inti = 5;// 變數iint*p = &i;// 指標p,指向變數iint*&pr = p;// 指標的引用,與p指向同一個變數icout << i << "  " << *p << "  " << *pr << endl;i = 10;cout << i << "  " << *p << "  " << *pr << endl;cout << "addr: " << p << "  " << pr << endl;// 指標的引用其它就是指標p的一個別名,和p有相同的地址pr = NULL;// 因此也可以給指標賦空cout << "addr: " << p << "  " << pr << endl;}

結果:

5  5  5

10  10  10

addr: 0045FE50  0045FE50

addr: 00000000  00000000

 

在函數中,指標的引用作為參數可以起到很巧妙的作用。

 

假設有一個書的類Book,基定義如下:

struct Book

{

    string isbn;

    string name;

    double price;

    string author;

};


現在需要這樣一個函數:有一個檔案存放著一本書的相關資訊(ISBN、書名、價格),現要從這個檔案中讀取資訊並賦給Book的對象。

 

要定義這樣一個函數,我們首先會想到的是有一個輸入(檔案的路徑)和一個輸出(Book的對象)。你可能會這樣定義函數:

Book* GetBookFromFile(const string& filePath);

這種方式你必須在函數體內建立Book的對象(也就建立一個Book的記憶體空間),但函數體內建立的記憶體空間只在函數的範圍內有效,在函數體外是無效的,也就是說返回的指標將指向一個任意的值,這將是非常危險的。

 

如函數內:

 


在函數被調用後:

 

 

 

 

 

既然不行,您應該會想到另外一種定義方式如下:

Book GetBookFromFile(const string& filePath);

沒錯,這樣定義確實可以,但需要在函數體內聲明一個Book的對象,函數傳回值的時候會進行一次對象的拷貝。這樣增加了一個對象拷貝的過程,使效率降低。

Book GetBookFromFile(const string& filePath){Book book;fstream fileInput(filePath);fileInput >> book.isbn >> book.name >> book.price;return book;}

 

 

 

 

 

您可能還會想到這種方式:

void GetBookFromFile(Book &book, const string& filePath);

沒錯,這確實可以解決上面的問題,不用再對對象進行拷貝。但新的問題又來了,上層調用這個函數時,如果要判斷返回book對象是否正確擷取了檔案的資訊得逐個地判斷基屬性是否空,如下代碼。這無疑加重了上層調用的負擔。

Book book;

GetBookFromFile(book, "E:\\book.txt");

if (!book.isbn.empty() && !book.name.empty() && book.price > 0)

{

    // TO DO ...

}

當然,這有一種改進的方式,就是把傳回值類型void改為bool,這樣就可以通過返回的bool值確定函數是否成功調用。

 

 

 

針對上面的這個問題,如果返回的是Book的指標,直接判斷返回的指標是否為NULL就可以。那麼您可以有以下兩種定義:

void GetBookFromFile(Book* book, const string& filePath);

void GetBookFromFile(Book*& book, const string& filePath);

當然,我是建議選擇第二種方式,因為引用確保了傳進來的指標有一個正確的值(引用必須在定義時被初始化)

 

定義如下:

 

void GetBookFromFile(Book* pBook, const string& filePath){if (pBook == NULL){return;}fstream fileInput(filePath);fileInput >> pBook->isbn >> pBook->name >> pBook->price;}

void GetBookFromFile(Book*& pBook, const string& filePath){if (pBook == NULL){return;}fstream fileInput(filePath);fileInput >> pBook->isbn >> pBook->name >> pBook->price;}

 

對這兩個函數,調用方式都可以如下:

Book* pBook = new Book();pBook->author = "SimileSunrise";GetBookFromFile(pBook, "E:\\book.txt");delete pBook;



 


指標與引用在函數調用中的不同

“int createbitree(Bitree &t )

為什麼int createbitree(bitree *t )不可以??
”
因為你主函數中定義的t本身就是指標,如果你直接用int createbitree(bitree *t)相當於傳值進去,如果要傳地址的話要用二級指標:
int createbitree(bitree **t)
 
c++中的函數引用與指標的不同?

#include <stdio.h>

void F(int a, int b){printf("hello %d %d\n", a, b);};

typedef void (&pF)(int, int);

int main()
{
int a = 1, b = 3;
pF x = F;
x(a, b);
printf("0x%X 0x%X", F, x);
}

全域變數是被儲存在記憶體中的全域靜態區的, 全域變數的聲明總是定義, 因為編譯器會將他們的值初始化為其預設值, 可以在全域範圍內定義變數, 但不能在全域範圍內實施操作, 因為操作是在函數中實現的, 你要分清初始化和賦值的不同, 所以比如有一個全域變數a;

int a; // 等價於int a(int());

則以下對a的操作都是違法的:

++a;
a--;
a += 1;
....

程式是由函數構建的, 而不是檔案構建的, 所以以上操作根本執行不到, 所以編譯不同過, 而且C/C++編譯器貌似只識別全域範圍內變數的聲明定義, 所以在你試圖global = 10的時候它認為你要建立一個不帶類型標識符的變數global, 所以給你一個錯誤; 另外它又發現你企圖聲明的這個變數與已存在的變數名有衝突, 所以它又給你一個錯誤...
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.