2012-01-07 4 views
6

Goプログラミング言語では、ポインタへのポインタはどのように役立つのでしょうか?ポインタに適したポインタは何ですか?

は(彼らは本当に有用ではない場合、なぜ彼らは違法ではない?)

+6

任意のデータへのポインタが便利です。ポインタはデータです。ポインターへのポインターは便利であり、ポインターへのポインターへのポインターもあります。 –

+0

私は同意しますが、ポインターの算術もポインタもGoのポインターよりも何もしていないので、実際には無用です。 – thwd

+0

Goにはポインタ演算があります。 'unsafe'パッケージを使って自由に使える' uintptr'を得ることができます。場合によっては、この方法でコードを効率的にすることもできますが、一般的には避けるべきです。 – tux21b

答えて

16

任意のデータ型の有用性は解決された問題で、問題を解決するために使用される方法に依存します。データ型が問題に適合しない場合は、問題に適合しないだけで、それ以上のことはありません。

Goプログラミング言語(他のほとんどのプログラミング言語と同様)は、簡略のルールに基づいており、プログラマが新しいデータ型を構築するために使用できます。これらの規則のいくつかは、次のとおり

  • *T:TS
  • struct { t T; u U ... }
  • の配列:成分
  • としてTを含む構造
  • [10]TをTへのポインタである新しいデータ型を作成します
  • ...

プログラマは、これらの単純なルールを作成することによって複雑なデータ型を作成できます。可能なデータ型の総数は、有用なデータ型の数を超えています。明らかに、有用ではないデータ型が存在する(存在しなければならない)。これは、新しいデータ型を構築するためのルールが単純であるという事実の自然な結果です。

タイプ**Tは、プログラムに表示される可能性が低いタイプのカテゴリに分類されます。 *****Tを書くことが可能であるという事実は、そのようなタイプが非常に有用でなければならないことを意味するものではない。


そして最後に、あなたの質問への答え:

はタイプ**Tは通常、我々はタイプTの別の値にタイプTの値のユーザーをリダイレクトするコンテキストで表示されますが、用値のすべてのユーザーにアクセスできない、またはユーザーを見つけることに時間がかかるような何らかの理由があります。

  1. の値はコピーしませんは
  2. (何らかの理由で)私たちは、私たちはすぐに別の値にタイプTの特定の値のすべてユーザーをリダイレクトにしたい
  3. ポインタを経由して値にアクセスするタイプTの値のすべてのユーザーが欲しいですそのような状況では

それは(1)私たちはOで3ステップを実施することを可能にするため、**Tを使用することは自然である:

type User_of_T struct { 
    Value **T 
} 

// Redirect all users of a particular value of type T 
// to another value of type T. 
func (u *User_of_T) Redirect(t *T) { 
    *(u.Value) = t 
} 
+0

それはしかし、スマートな解決策です。 – Tarik

3

Cではポインタへのポインタはかなり一般的です。例えば:

  • 複数次元アレイ(例えば、文字列の配列、char** argvはここで最も顕著な例であるかもしれない)出力パラメータゴーで

として

  • ポインタが、ポインタへのポインタでありますかなり珍しい。ポインタで配列にアクセスする代わりに、スライスタイプ(ポインタも内部的に格納されます)があります。したがって、Goでスライススライスを使用して同じ種類の間接参照を取得することはできますが、通常は**intのように表示されません。

    ただし、2番目の例は、Goプログラムにも適用されます。たとえば、パラメータとして渡されたポインタを変更できる関数があるとします。その場合、元のポインタを変更できるように、そのポインタへのポインタを渡す必要があります。関数はある値(しばしばある種のエラーコード)を返すだけで、追加のポインタを返す必要がある場合は、そのポインタへのポインタを出力パラメータとして使用する必要があるため、Cでは非常に一般的です。しかし、Goの関数は複数の値を返すことができるので、ポインタへのポインタの出現もまれです。しかし、それらはまだ有用であり、場合によってはより良いAPIにつながるかもしれません。

    例えば、atomic.StorePointer関数は、標準ライブラリのポインタへのポインタのための稀ではあるが、よく隠されたユースケースの1つです。

  • 5

    関数へのポインタを渡すと、関数はコピーを取得します。だから、与えられたポインタに新しい値を元に、それを割り当てることにはなりません割り当てる:

    type Smartphone struct { 
        name string 
    } 
    
    type Geek struct { 
        smartphone *Smartphone 
    } 
    
    func replaceByNG(s **Smartphone) { 
        *s = &Smartphone{"Galaxy Nexus"} 
    } 
    
    func replaceByIPhone(s *Smartphone) { 
        s = &Smartphone{"IPhone 4S"} 
    } 
    
    func main() { 
        geek := Geek{&Smartphone{"Nexus S"}} 
        println(geek.smartphone.name) 
    
        replaceByIPhone(geek.smartphone) 
        println(geek.smartphone.name) 
    
        replaceByNG(&geek.smartphone) 
        println(geek.smartphone.name) 
    } 
    

    出力は次のようになります。ここでは

    Nexus S 
    Nexus S 
    Galaxy Nexus 
    
    +0

    本当に便利な答えは、これは私が別の関数でスライスを修正しようとしたことです –

    2

    Linus Torvalds氏は、最近のポインタへのポインタは(Cで)良い味とコーディングにつながる方法を述べました。 (とりわけ)Brian Barto's blog postを参照してください。

    関連する問題