2010-06-21 155 views
6

可能重複:
How do pointer to pointers work in C?爲什麼和什麼時候值得使用指針指針?

你好,

Altough我想我通過編程新手階段我仍然有一些問題,不知怎的,我無法找到他們解釋。是的,有很多「如何」超越,但幾乎總是沒有人解釋爲什麼和/或何時一種技術是有用的。

在我的案例中,我發現在某些情況下,在C++中使用了指針指針。不是足夠的指針嗎?哪些好處? 何時何地應該使用指向指針的指針?我覺得在這件事上一點點的迷失了方向。

我希望時間有經驗的專家能夠迴應這種擔心,希望由其他沒有經驗豐富的程序員共享。 ;-)

謝謝大家。

Julen。

+2

重複的是什麼? – 2010-06-21 09:30:48

+0

http://stackoverflow.com //questions/897366/how-do-pointer-to-pointers-work-in-c – tster 2010-06-21 12:00:01

+0

對不起,這是重複的。 ( – Julen 2010-06-21 13:22:17

回答

8

那麼,這是一個很難回答這樣一個普遍的問題。

C++程序員的第一個答案肯定是:不要在C++中使用指針!由於你有很多比指針更安全的處理問題的方法,因此你的目標之一就是避免它們在第一位:)

因此指針指針很少用在C++中。它們主要用於C.首先,因爲在C中,字符串是「char *」,所以當你需要一個「指向C字符串的指針」時,以「char **」結束。其次,因爲你在C中沒有引用,所以當你需要一個修改一個指針的函數或者一個指針作爲輸出值時,你需要給一個指針參數指針。你通常在分配內存的函數中發現,因爲它們給你一個指向分配內存的指針。

如果你採用C++方式,儘量避免使用指針,那麼通常有更好的方法。

my2c

+2

-1「不要在C++中使用指針」。真的嗎?所以,我應該忘記DirectX編程, OpenGL,com對象,直接的API調用?沒有指針的編程有什麼意義?這聽起來像是無用的syntaxic糖。 – SigTerm 2010-06-21 14:10:53

+0

@SigTerm:從我那裏得到這個建議的+1。當要降級到低級別的API時更容易需要(像着名的'&v [0]')比在低級代碼中做所有的東西。近十年來,我編寫並維護了幾個MLoC C++應用程序的一部分(很可能已安裝在您的機器上,順便說一下)。最後我的部分是> 100kLoC。然而,那裏只有三個「刪除」,這主要是由於歷史原因。 – sbi 2010-06-22 08:38:39

+0

@SigTerm:首先感謝你解釋你的downvote。其次,我不是你所說的API的專家,但我認爲他們是C API,不是嗎?當然,在C++中使用指針的一個用例是使用C API :)我也許應該說「嘗試在使用C++設計事物時不要使用指針」。當你使用API​​時,你別無選擇。而且,由於OP問題是關於指針的指針,因此在我看來,設計C++代碼以使用指向指針的指針並不是一種理想的方式。實際上,當我編寫指針時,我想我會使用原始指針,因爲我使用的指針非常廣泛;) – neuro 2010-06-22 09:03:44

1

實際上有兩個用例。

首先,當你調用一個函數時,必須返回多個值,其中一些是指針。然後,你會爲她提供一個指針的地址,因此它可以在所指的指針填寫:當你想要做的稀疏二維數組

int *p1 = 0, *p2 = 0, *p3 = 0; 
multi_malloc(&p1, &p2, &p3); // Allocates three pointers 

二是:

int main(int argc, char **argv)

這是指向指針的指針。 argv [i]是一個指向char的指針。這樣,argv [i] [j]就是第i行的char j。

您將很高興聽到指針指向指針的指針幾乎爲零。 int ***p;幾乎沒有用處。

+1

這是非常C.在C++中,你有指針的引用,你可以做到這一點與他們在一個更簡單的(因此,錯誤傾向) – 2010-06-21 09:22:04

+1

嘿嘿''int *** p'看起來像你審查了一些東西 – detly 2010-06-21 09:22:21

+2

IIRC,根據C++標準,你可以有多達8級的去引用。 * p – Aamir 2010-06-21 10:24:43

3

指針的指針與C最相關。在C++中,你很少需要它們。在那裏你可以使用std lib或者引用的容器。

有兩種流行的用例在C雖然:

  1. 指針數組,最突出用作argv的主():該指針表示的地址的參數串的陣列(類型char *)。在C語言中,[]運算符用於指向任何東西的指針,因爲指向任何東西的指針都等同於數組。

  2. 函數參數,表示存儲地址的地方。用例:在C中,返回值通常用於錯誤處理或狀態信息。參數用於承載有效載荷。一個例子:函數「返回」一個地址到新分配的內存,但使用一個參數。你給這個函數一個指向應該指向數據的指針的指針。該函數會覆蓋該空間,因此需要一個指向指針的指針。

6

在C中,一個參數傳遞給它的變化,通過指針的功能。對於舊代碼或遺留代碼(int main(int argc, char** argv)),對於將從C(COM/XPCOM)訪問的代碼或由曾用於C(或C風格)的人編寫的代碼,您將看到與C++相同的舊代碼或舊代碼。從「純C++」的角度來看,使用指針指針在大多數情況下是編碼風格較差的標誌,因爲大多數需要**構造的情況可以(也應該)被重構爲使用更安全的替代方案(如std::容器,或*&參數)。

4

我能想到兩個用例。

一個是陣列從C.陣列繼承自動衰減到指針在很多情況下他們的第一元件。如果你碰巧有一個指針數組,你會得到一個指針指針。
(當你有指針的std::vector類似的東西會發生,順便說一句:指針是一個完美的隨機訪問迭代器,我的確看到了使用指針標準庫實現對std::vector<>::iterator爲指針的std::vectorv.begin()會返回一個指針。一個指針)

另一個是對於函數參數。對於函數參數,每個指針取一些東西指示調用者可能會調用該函數,即使它們沒有要傳入的對象;那麼他們可以通過NULL。 (否則爲什麼需要一個指針而不是參考?請參閱here瞭解更多詳情)。
對指針進行非const引用將指示被調用的函數可能會爲該指針分配一個新地址。
因此,如果指向指針的指針指示該函數可能會爲指針分配一個新地址,如果調用者傳遞給它的指針,但也可以用NULL調用。 例如:

void f(int** ppi); 
void g(int i); 

void h() 
{ 
    f(NULL); // call `f()` only for its side-effects 

    int* pi = NULL; 
    f(&pi); // call `f()` and get some object in *pi 
    if(pi) 
    g(*pi); // use result 
} 
3

何處或何時應當使用一個指針的指針?

在一個函數中,如果調用者請求,可以有選擇地返回指向調用者的指針。常用於系統API,某些COM對象等。

int f(void** p = 0){ 
    //....... 
} 

如果調用方提供p,則函數將指針傳遞給p。如果調用者不提供p,則不返回指針。在某些情況下可能對調試有用。

哪些是好處?

這個問題太廣泛了。看,這是一個非常簡單的技術,沒有某種神祕的好處。你必須使用它。就這樣。這個概念沒有隱藏的含義和祕密優勢 - 它相當於問「在英語中使用字母」的優點是什麼「。

+0

+1這是非常主流的,但很多其他答案都說'你不應該這樣做!' – Will 2010-06-21 11:58:31

2

你只有在使用手動內存管理時才使用它們,這在C++中非常罕見,因此它們非常沒用。即使是常規指針,在大多數情況下也是有問題的。