ベクターの割り当ては、値またはGoogleのGo言語の参照によってコピーされますか?

StackOverflow https://stackoverflow.com/questions/1806673

  •  05-07-2019
  •  | 
  •  

質問

次のコードでは、ペグパズルを1つ作成し、その上で移動を実行します。これにより、movesAlreadyDoneベクトルに移動が追加されます。次に、別のペグパズルを作成し、その上で移動を実行します。これにより、movesAlreadyDoneベクトルに移動が追加されます。 2番目のベクトルの値を出力すると、最初のベクトルからの動きと2番目のベクトルからの動きが含まれます。なぜ値ではなく参照によって割り当てられているように見えるのですか?ベクターの割り当ては、値またはGoogleのGo言語の参照によってコピーされますか?

package main

import "fmt"
import "container/vector"

type Move struct { x0, y0, x1, y1 int }

type PegPuzzle struct {
    movesAlreadyDone * vector.Vector;
}

func (p *PegPuzzle) InitPegPuzzle(){
    p.movesAlreadyDone = vector.New(0);
}

func NewChildPegPuzzle(parent *PegPuzzle) *PegPuzzle{
    retVal := new(PegPuzzle);
    retVal.movesAlreadyDone = parent.movesAlreadyDone;
    return retVal
}

func (p *PegPuzzle) doMove(move Move){
    p.movesAlreadyDone.Push(move);
}

func (p *PegPuzzle) printPuzzleInfo(){
    fmt.Printf("-----------START----------------------\n");
    fmt.Printf("moves already done: %v\n", p.movesAlreadyDone);
    fmt.Printf("------------END-----------------------\n");
}

func main() {
    p := new(PegPuzzle);
    cp1 := new(PegPuzzle);
    cp2 := new(PegPuzzle);

    p.InitPegPuzzle();

    cp1 = NewChildPegPuzzle(p);
    cp1.doMove(Move{1,1,2,3});
    cp1.printPuzzleInfo();

    cp2 = NewChildPegPuzzle(p);
    cp2.doMove(Move{3,2,5,1});
    cp2.printPuzzleInfo();
}

どんな助けも大歓迎です。ありがとう!

役に立ちましたか?

解決

答えに付随しますが、 vector.New はGoの最近のバージョンから削除されました。書く必要があります

func (p *PegPuzzle) InitPegPuzzle(){
    p.movesAlreadyDone = new (vector.Vector);
}

元のコードでは、コピーするものはベクターへのポインターです。これは、Cのポインターとまったく同じです。「参照渡し」と呼ぶことができます。必要に応じて、ポインタです。

ベクター全体をコピーするには、 InsertVector <を使用します。 / a>:

func (p *PegPuzzle) InitPegPuzzle(){
    p.movesAlreadyDone = new (vector.Vector);
}

func NewChildPegPuzzle(parent *PegPuzzle) *PegPuzzle{
    retVal := new (PegPuzzle);
    retVal.InitPegPuzzle ();
    retVal.movesAlreadyDone.InsertVector (0, parent.movesAlreadyDone);
    return retVal
}

これにより、完全に一意のコピーが作成されます。

他のヒント

コードでは、 movesAlreadyDone * vector.Vector です。 retVal.movesAlreadyDone = parent.movesAlreadyDone; を割り当てると、参照がコピーされます。 retVal.movesAlreadyDone または parent.movesAlreadyDone のいずれかでベクターの変更が行われると、同じ基になるベクターを変更することになります。

1つのベクターのコンテンツを別のベクターにコピーする場合は、ソースベクターを反復処理し、その要素をデスティネーションベクターにプッシュする必要があります。そのように:

for n := range srcVect.Iter() {
    dstVect.Push(n);
}
scroll top