【问题标题】:How does pointer dereferencing work in Go?指针解引用在 Go 中是如何工作的?
【发布时间】:2015-01-20 23:00:53
【问题描述】:

我正在阅读http://tour.golang.org/ 的 golang 教程,并在 example 29 中尝试了一些东西

这里复制原始示例供您参考:

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

它非常基础,展示了如何创建这个花哨的新结构 Vertex 的实例。不过,Example 28 显示了通过指向顶点的指针来操作顶点,因此我稍微修改了示例并对输出感到惊讶。这是修改:

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

还有输出:

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

让我吃惊的是t不是{4, 2},这似乎意味着改变q.X改变了q指向的结构的实例。来自 C/C++ 背景,这对我来说似乎是非常奇怪的行为。

那么,这里到底发生了什么?为什么使用q.X = 4改变顶点不传播到t

【问题讨论】:

  • 记住:Go 没有像 int &x 这样的 C++ 样式引用。只有好的旧指针。
  • 如果这有助于更好地可视化这一点play.golang.org/p/9GqtFpbIHWw

标签: pointers go


【解决方案1】:

t := *q 复制q 指向的结构体。

如果您想观察qt 的变化,请使用指针:

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() {
    t := q
    q.X = 4
    u := *q
    fmt.Println(p, q, r, s, t, u, *t == u)
}

这会产生您可能正在寻找的输出。

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

我不确定你觉得什么特别奇怪。 C 和 C++ 的行为方式相同。考虑以下几点:

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

此 C++ 代码的输出显示相同的行为:

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

【讨论】:

  • 感谢您的解释。 C++ 可能会这样做,但 C 绝对不会,除非您显式复制实例。
  • 澄清一下——听起来像“t := *q 复制q 指向的结构”是我正在寻找的答案。您提供的 C++ 代码不能按原样编译,当我尝试使用 new Vertex 时,g++ 仍然会给我一些错误,因此除非对其进行编辑,否则不应将其视为合理的比较例子。
  • 我正在使用一些 C++11 语法来初始化结构,所以你必须启用 C++11 模式来编译它(通常-std=c++11 可以解决问题)。示例见此处:coliru.stacked-crooked.com/a/2a304f24025b4d9d
  • 所以这并不奇怪,因为我们在 C++ 中看到了相同的行为? Python 和 JS 不会这样做,我猜 C 也不会。
  • @yangmillstheory Python 和 JS 不这样做,因为 Python 和 JS 没有指针。 Go、C 和 C++ 都有指针并且都以这种方式运行。当您将取消引用指针的结果分配给新变量时,该变量会获得其指向的值的副本。
猜你喜欢
  • 2021-12-08
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多