ホームページ >バックエンド開発 >Golang >Go でポインターを逆参照しても元の値が変更されないのはなぜですか?

Go でポインターを逆参照しても元の値が変更されないのはなぜですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-08 12:53:11302ブラウズ

Why Doesn't Dereferencing a Pointer in Go Modify the Original Value?

Go でのポインター逆参照: 何が起こっていますか?

Go でのプログラミングの世界を詳しく調べると、特に次のような場合にポインター逆参照に関連する興味深い動作に遭遇することがあります。構造体を使った作業。次の例を考えてみましょう:

package main

import "fmt"

type Vertex struct {
    X, Y int
}

var (
    p = Vertex{1, 2}  // has type Vertex
    q = &Vertex{1, 2} // has type *Vertex
    r = Vertex{X: 1}  // Y:0 is implicit
    s = Vertex{}      // X:0 and Y:0
)

func main() {
    t := *q
    q.X = 4
    u := *q
    fmt.Println(p, q, r, s, t, u, t == u)
}

このコードを実行すると、驚くべき結果が生成されます:

{1 2} &{4 2} {1 0} {0 0} {1 2} {4 2} false

q.X を変更した後、t が {4, 2} に変更されると予想されるかもしれませんが、これは変更されません。起こる。この動作の理由は何ですか?

ポインターの逆参照の説明

これを理解するための鍵は、ポインターの逆参照です。 Go では、ポインター (*q など) を逆参照すると、それが指す値のコピーが作成されます。したがって、 t := *q は、q によって参照される Vertex struct の別のコピーを作成します。

例 28 の変更を明確にしました:

変更した例では、次のように設定すると、 q.X = 4 の場合、q が指す構造体のみを変更します。 t はコピーであるため、元の値が保持されます。

Go と C/C の比較

C/C の観点から見ると奇妙に見える動作について言及しました。ただし、C/C も同様に動作します。次の例を考えてみましょう:

#include <iostream>

struct Vertex
{
    int x;
    int y;
};

int main()
{
    Vertex v = Vertex{1, 2};
    Vertex* q = &v;
    Vertex t = *q;
    q->x = 4;
    std::cout << "*q: " << *q << "\n";
    std::cout << " t: " << t << "\n";
}

この C コードは同じ動作を生成します:

*q: { 4, 2 }
t: { 1, 2 }

結論

要約すると、Go でポインタを逆参照すると、次のようになります。基になる値のコピーを作成しています。ポインターを介して加えられた変更を監視するには、次の変更例のようにポインター自体を使用する必要があります。

func main() {
    t := q
    q.X = 4
    u := *q
    fmt.Println(p, q, r, s, t, u, *t == u)
}

これにより、期待される出力 {1 2} &{4 2} {1 0} が生成されます。 {0 0} {4 2} {4 2} true。

以上がGo でポインターを逆参照しても元の値が変更されないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。