Are vector assignments copied by value or by refer

2019-07-29 07:30发布

问题:

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:

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.



回答2:

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


标签: vector go