2014-11-23 7 views
7

Idę przez golang tutoriali na http://tour.golang.org/ i eksperymentował nieco z niektórych rzeczy w example 29Jak działa dereferencja wskaźnikowa w golangu?

celach informacyjnych, oryginalny przykładem jest kopiowany tutaj:

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() { 
    fmt.Println(p, q, r, s) 
} 

To dość podstawowe, pokazując jak utworzyć wystąpienia tej nowej, fantazyjnej struktury, Vertex. Example 28, ale pokazuje manipulowanie wierzchołkiem przez wskaźnik do niego, więc trochę zmodyfikowałem przykład i byłem zaskoczony przez wynik. Oto modyfikacja:

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

a wyjście:

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

Tym, co zaskoczyło mnie to, że t nie jest {4, 2}, który wydaje się oznaczać, że zmiana q.X zmienił instancji struktura, na którą wskazano obiekt. Pochodzenie z tła w C/C++ wydaje mi się dziwnym zachowaniem.

Co się tutaj dzieje? Dlaczego użycie q.X = 4 do zmiany wierzchołka nie jest propagowane na t?

+0

Pamiętaj: Go nie ma odniesienia C++ stylu jak 'int & x'. Tylko dobre stare wskazówki. – fuz

Odpowiedz

16

t := *q tworzy kopię struktury wskazanej przez q.

Jeśli chcesz obserwować zmiany q przez t, a następnie trzymać się wskaźnik:

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

To daje wyjście to prawdopodobnie szukasz.

{1 2} &{4 2} {1 0} {0 0} &{4 2} {4 2} true 

Nie jestem pewien, co wydaje ci się wyjątkowo dziwne. C i C++ zachowują się w ten sam sposób. Rozważmy następujący:

#include <iostream> 

struct Vertex 
{ 
    int x; 
    int y; 
}; 

std::ostream& operator<<(std::ostream& out, const Vertex& v) 
{ 
    out << "{ " << v.x << ", " << v.y << " }"; 
    return out; 
} 

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

Wyjście tego kodu C++ pokazuje ten sam problem:

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

Dzięki za wyjaśnienie. C++ może to zrobić, ale C zdecydowanie nie, chyba że jawnie skopiujesz instancję. – Kevin

+0

Aby wyjaśnić - brzmi to jak "' t: = * q' sprawia, że ​​kopia struktury wskazywanej przez 'q'" jest odpowiedzią, której szukałem. Podany przez Ciebie kod C++ nie kompiluje się tak jak jest, a kiedy próbuję użyć 'nowego Vertex',' g ++ 'nadal daje mi pewne błędy, więc jeśli nie zostanie to zmienione, nie powinno być traktowane jako rozsądne. przykład porównania. – Kevin

+0

Używam jakiejś składni C++ 11 do inicjowania struktury, więc musisz włączyć tryb C++ 11, aby ją skompilować (zwykle '-std = C++ 11' robi lewę). Zobacz tutaj: http://coliru.stacked-crooked.com/a/2a304f24025b4d9d – zmb

Powiązane problemy