2012-02-12 180 views
1

所以,我明白指針是什麼,引用什麼意思,並且對這個「堆」有一個模糊的理解。當我們開始失去對事物的控制時,就是當我們使用這些概念引入函數和類時,例如發送指針,返回指針等。指針與參考

如果通過引用和傳遞指針本質上執行相同的功能,那麼使用它們的優點是什麼?基本上都是通過引用傳遞並在被調用的函數之外操作對象。

因此,通過參考:

#include <iostream> 

class student{ 
public: 
    int semesterHours; 
    float gpa; 
}; 

void defRefS(student &refS); 
void defPointerS(student *Ps); 
void defValueS(student cS); 

int main() 
{ 
    student s; 
    defRefS(s); //Here, 
    std::cout << "\nBack in main we have " << s.semesterHours << " hours"; 
    std::cout << "\nBack in main the GPA is: " << s.gpa; 


    student *Ps = &s; 
    defPointerS(&s); //And here is where I get confused 
    std::cout << "\nBack in main we have " << s.semesterHours << " hours"; 
    std::cout << "\nBack in main the GPA is: " << s.gpa; 

    defValueS(s); 
    std::cout << "\nBack in main object S has: " << s.semesterHours << " hours"; 
    std::cout << "\nBack in main object S has: " << s.gpa << " GPA\n\n"; 

} 

void defRefS(student &refS) //Passing by reference to object 
{ 
    refS.gpa = 4.0; 
    refS.semesterHours = 12; 
    std::cout << "\n------------- Reference Function ------------"; 
    std::cout << "\n\nObject S has: " << refS.semesterHours << " hours"; 
    std::cout << "\nObject S has: " << refS.gpa << " GPA"; 
} 

void defPointerS(student *Ps) //Passing a pointer to the object 
{ 
    Ps->gpa = 5.0; 
    Ps->semesterHours = 14; 
    std::cout << "\n\n------------- Pointer Function ---------------"; 
    std::cout << "\n\nNow object S has: " << Ps->semesterHours << " hours"; 
    std::cout << "\nNow object S has: " << Ps->gpa << " GPA"; 
} 

void defValueS(student cS) //Passing the object by value 
{ 
    cS.gpa = 100; 
    cS.semesterHours = 50; 
    std::cout << "\n\n------------- Value Function ------------------"; 
    std::cout << "\n\nObject S has: " << cS.semesterHours << " hours"; 
    std::cout << "\nObject S has: " << cS.gpa << " GPA"; 
} 

按引用傳遞本質上允許的符號是類似的,因爲,我想,在各方面refSs對象。所以,這導致使用函數來操縱對象的簡單方法。

傳遞指針很容易理解。它只是一個指向對象的指針。雖然在以上代碼中如何處理:

void defRefS(student &refS); 
void defPointerS(student *Ps); 
void defValueS(student cS); 

所有這些函數是否只定義爲與學生類一起使用?那麼,這些函數只能將參考,指針和對象的值傳遞給這個特定的類?

defRefS(s); //Here, 
defPointerS(&s); //And here is where I get confused 
defValueS(s); 

如果按引用傳遞,你不應該傳遞一個對象的地址嗎?所以,對我而言,它更多地在參考函數中傳遞指針函數的參數。

函數defPointerS被定義爲接受指針;我正在發送地址?

+1

誰告訴你這個所謂的「堆」不應該支付的「教你的C++」。取而代之的是一本好書。 – 2012-02-12 20:18:10

+0

@KerrekSB我沒有看到教授動態管理變量的常見實現的問題 – 2012-02-12 20:41:23

+0

@SethCarnegie:一百個困惑的SO問題,應該從來都不足以成爲我的理由...... – 2012-02-12 20:43:13

回答

1

當您在函數/類型定義中使用字符&(如void defRefS(student &refS);student &refS) - 您正在定義一個引用。該值將是一個參考。

當您在一個對象(變量)上使用相同的運算符(即:相同的字符&)時,您將獲取該特定對象的地址(如student *Ps = &s;defPointerS(&s);)。該值將是一個指針。

還困惑嗎?然後不要讀下一句。運算符&也是一個按位AND,當在語句中時,例如0x1 & 0xFF產生1.返回值將是語句中最大整數大小的整數。

0

當你有student s;變量,你想通過它來運作f這需要student類型(按值傳遞),或student&(通過引用傳遞)的說法,你只需要調用f(s)。如果按值通過s,則會創建s的副本,並在函數體中使用s的副本。如果通過引用傳遞它,則直接使用對象s。引用不能爲NULL,這在很多情況下都是很有利的。

當這個參數的類型是student*(也通過引用傳遞)時,由於指針需要用指向它的地址進行初始化,因此可以調用f(&s)

您也應該檢查:Pointer vs. Reference

2

我猜你是剛開始在C++中。不要擔心堆,這是一個較低層次的概念,您將在稍後瞭解這些概念。如果你真的感興趣,new運算符和malloc在堆上分配內存(new實際上也調用對象的構造函數,給你一個動態對象)。你可以把它看作只是一個空間,你可以放入你想要的東西)。

關於指針和引用,它們在大多數情況下都是可以互換的(正如你想象的那樣)。這取決於你想如何構建你的代碼。

在C++中,指針無處不在,人們通常會傳遞指針而不是通過引用傳遞。指針被更頻繁地使用的原因之一是因爲動態內存分配的工作原理(new運算符或malloc) - 它返回一個指針 - 並且你做了很多工作。所以一般來說,你會通過指針指向一個對象。

絕對必須使用引用的罕見場合是在複製構造函數或定義運算符中。

我可能錯過了一些情況,但這是它的要點。

+1

'new'不是(僅僅)關於分配;最重要的是它創建一個動態*對象*(即它調用構造函數)。不要混淆記憶和物體;它們在C++中是不同的概念。 – 2012-02-12 20:39:46

+0

這是真的,我會解決這個問題。 – Pochi 2012-02-12 20:55:19

+1

新的不會像malloc一樣在堆上分配內存;它分配它在免費商店 – 2012-02-12 21:34:57

0

初學者請參閱What are the differences between pointer variable and reference variable in C++?

當通過引用傳遞變量,你可以把它看作含蓄地地址,這樣你就不必寫&,但它仍然這樣做是爲了你(這就是爲什麼你會得到,如果一個錯誤你傳遞一個常量,如「5」作爲參考參數)。它也隱含在函數內部解引用它,所以你不必寫「*」。

「函數defPointerS被定義爲接受指針;我正在發送它的地址?」指針是一個地址(或者更恰當的說,是一個存儲內存地址值的變量)。

「那麼,這些函數只能將參照,指針和對象的值傳遞給這個特定的類?」這些類型表明如果您嘗試將另一個類的實例傳遞給此函數,您將收到編譯器錯誤。然而,C++沒有強制執行類型安全性,您可以繞過它並強制它通過「reinterpret_cast」傳遞指向其他類型對象的指針。在大多數情況下,這是行不通的。

1

使用一個優於另一個的優點是什麼?

很好的理由使用供輸入參數函數的引用:參考永遠不能爲空,這樣你就不會需要檢查是任何地方的指針指向。

使用指針傳遞函數的輸入參數的好理由:您可以使用指針算術,因此您可以傳遞數組(這在C++中不推薦)。所以最好在大多數情況下堅持引用。

如果按照引用傳遞,你不應該傳遞一個對象的地址嗎? - 不,你傳遞一個對象。和號附近的參數意味着參數在不復制的情況下引用對象。

函數defPointerS被定義爲接受指針;我正在發送地址? - 應用於r值時的運算符「&」產生指向對象的指針。

2

你得到的符號(&)的兩種用法之間的混淆。在一種情況下,它是一個操作員,在另一種情況下,它是聲明類型的一部分。

int x = 5; 
int* y = &x; // (1) Here it's an operator 
int& z = x; // (2) Here it's part of the type of y 

在線路(1)中,我們宣佈,並且限定了一個名爲y變量這是pointer to int類型。這意味着變量y應該包含類型爲int的變量的地址。要獲取變量的地址,請使用&作爲運算符。因此,&xx的地址,我們將它存儲在指針中。 y現在是指向x的指針。在第(2)行中,我們定義了一個變量z,其類型爲reference to int。由於我們綁定X本refernece,這意味着我們可以使用z作爲另一名x。修改z將修改x(也是值y點!)。

所以,當你有一個函數,指針,像void func(int* p),你需要傳遞一個int的地址。要做到這一點,你就可以直接通過指針或採取int地址:

int x = 5; 
func(&x); 

如果你有一個函數,它的參考,像void func(int& r),你只需要通過它的int。該參考文獻將涉及相同的int

int x = 5; 
func(x); 

這些可以以類似的方式使用:將參數傳遞給函數,以便函數可以修改它或避免複製。但是,指針參數還允許您將空指針傳遞給該函數。這不適用於引用,因爲引用必須始終綁定到某個東西。另外,一旦綁定了引用,就不能將其引用到其他對象。

參考一般都更方便,更不依賴於C風格的指針操作。在C++中,您通常只需要使用引用,如果必須使用指針。詳情請參閱the C++ FAQ