1

在下面的代码中,我创建了一个钉子拼图,然后对其进行移动,将移动添加到它的 moveAlreadyDone 向量中。然后我创建另一个挂钩拼图,然后在其上移动,向它的 moveAlreadyDone 向量添加移动。当我为第二个向量打印出该向量中的值时,它具有从第一个向量的移动以及从第二个向量的移动。谁能告诉我为什么它似乎是通过引用而不是价值分配?在 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();
}

任何帮助将不胜感激。谢谢!

4

2 回答 2

1

在您的代码中,movesAlreadyDone*vector.Vector; 当您分配时retVal.movesAlreadyDone = parent.movesAlreadyDone;,您正在复制参考。任何时候对任何一个向量进行修改,retVal.movesAlreadyDone或者parent.movesAlreadyDone您将修改相同的底层向量。

如果要将一个向量的内容复制到另一个向量,则需要遍历源向量并将其元素推送到目标向量。像这样:

for n := range srcVect.Iter() {
    dstVect.Push(n);
}
于 2009-11-27T04:39:18.000 回答
1

附带答案,但vector.New已从 Go 的最新版本中删除。你需要写

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

在您的原始代码中,您要复制的内容是指向向量的指针。这与 C 中的指针相同。如果您愿意,可以将其称为“通过引用”,但它们是指针。

要复制整个向量,请使用InsertVector

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
}

这给出了一个完整的唯一副本。

于 2009-11-27T05:28:59.913 回答