在Google的Go语言中,向量赋值是按值还是按引用复制的?

huangapple go评论106阅读模式
英文:

Are vector assignments copied by value or by reference in Google's Go language?

问题

在以下代码中,我创建了一个木板拼图,然后对其进行了一次移动,将移动添加到其movesAlreadyDone向量中。然后我创建了另一个木板拼图,然后对其进行了一次移动,将移动添加到其movesAlreadyDone向量中。当我打印出第二个木板拼图中该向量的值时,它包含了第一个木板拼图中的移动以及第二个木板拼图中的移动。有人能告诉我为什么它似乎是通过引用而不是值进行赋值的吗?在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();
}

非常感谢任何帮助!谢谢!

英文:

In the following code, I create one peg puzzle then do a move on it which adds a move to its movesAlreadyDone vector. Then I create another peg puzzle then do a move on it which adds a move to its movesAlreadyDone vector. When I print out the values in that vector for the second one, it has the move in it from the first one along with the move from the second one. Can anyone tell me why it seems to be assigning by reference and not value? Are vector assignments copied by value or by reference in Google's Go language?

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();
}

Any help will be greatly appreciated. Thanks!

答案1

得分: 1

在你的代码中,movesAlreadyDone 是一个 *vector.Vector;当你赋值 retVal.movesAlreadyDone = parent.movesAlreadyDone; 时,你是在复制一个引用。无论是在 retVal.movesAlreadyDone 还是 parent.movesAlreadyDone 上进行向量修改,你都会修改同一个底层向量。

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

for n := range srcVect.Iter() {
    dstVect.Push(n);
}
英文:

In your code, movesAlreadyDone is a *vector.Vector; when you assign retVal.movesAlreadyDone = parent.movesAlreadyDone;, you are copying a reference. Anytime a vector modification is done on either retVal.movesAlreadyDone or parent.movesAlreadyDone you'll be modifying the same underlying vector.

If you want to copy the contents of one vector to another you will need to iterate through the source vector and push its elements to the destination vector. Like so:

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

答案2

得分: 1

在你的原始代码中,你正在复制的是指向向量的指针。这与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
}

这将得到一个完整的唯一副本。

英文:

Incidental to the answer, but vector.New has been deleted from recent versions of Go. You need to write

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

In your original code, the things you are copying are pointers to vectors. This is just the same as pointers in C. You can call it "by reference" if you like, but they're pointers.

To copy an entire vector, use 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
}

This gives a complete unique copy.

huangapple
  • 本文由 发表于 2009年11月27日 12:07:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/1806673.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定