结构中类的语义

Semantics of a class within a struct

提问人:CodeBoxRoll 提问时间:9/26/2022 最后编辑:Ken WhiteCodeBoxRoll 更新时间:9/26/2022 访问量:105

问:

我正在审查数据结构,在链表方面遇到了一些我从未意识到的东西。这个具体的例子是针对链表的,但我认为这个概念将主要围绕结构中遵循引用语义的属性(值语义)。

情况如下:我声明了一个新节点,并说这个新节点和 LinkedList 中共享相同的引用。然后,我更改 的值。我假设由于新节点和引用内存中的相同空间,它们都会反映更新。然而,事实并非如此。 显示更新“,但新节点不会显示。请参阅下面的代码。headheadheadhead

public struct LinkedList<Value> {
    public var head: Node<Value>?

    public init() {}
    /* 
    append, push, isEmpty, insert, pop functions
    */
}



public class Node<Value> {
    public var value: Value
    public var next: Node?

    public init(value: Value, next: Node? = nil) {
        self.value = value
        self.next = next
    }
}

var list = LinkedList<Int>()
list.append(1)
list.append(2)
list.append(3)

let node = list.head
list.head = list.head?.next

print(list.head)  // prints 2 -> 3
print(node)       // prints 1 -> 2 -> 3

由于是一个类,我本来会想到这一点,并且都会反映对任何一个所做的更新。为什么上面的类语义的行为与下面的不同:Nodelist.headnode

// Reference type example
class C { var data: Int = -1 }
var x = C()
var y = x                       // y now points to the same memory address as x
x.data = 42                     // changes the instance referred to by x (and y)
println("\(x.data), \(y.data)") // prints "42, 42"
SWIFT 数据结构 链表 值传递

评论

0赞 timbre timbre 9/26/2022
你说“x 被复制到 y”的地方 - 它不是。 只需指向内存中与 相同的地址,即可获得对象所在的位置。因此,当然,当您更改对象时,将打印相同的值(来自内存),而不管您用于访问该值的引用如何。这是“按引用”的核心,而不是“按值”的核心,后者是访问结构的方式。yx
0赞 CodeBoxRoll 9/26/2022
@khjfquantumjj 我理解这一点,但我看到评论是多么令人困惑。我会将其更新为“y 指向与 x 相同的内存地址”。我明白为什么 x 和 y 示例有效。我不明白为什么我上面列出的示例的行为与 x 和 y 示例不同。
1赞 Alexander 9/26/2022
仅当对象具有值语义时,包含对对象(类的实例)的引用的结构才具有值语义。例如: 是一个结构,包含对堆分配的缓冲区(它是类的实例)的引用,但具有在突变时复制该缓冲区的逻辑,从而导致整体值语义Array

答:

2赞 Thang Phi 9/26/2022 #1

因为你设置并且是类。因此,当变量赋值给类变量时,它会指向内存中存储该类变量的地址。LinkedListNode

从代码的这 2 行中,您可以看到

let node = list.head
list.head = list.head?.next

第一个是指向存储的内存地址的表示。表示两者此时都分配给相同的内存地址。node = list.headnodelist.headnodelist.head

第二个是指向存储的内存地址的表示。表示两者此时不分配给相同的内存地址。list.head = list.head?.nextlist.headlist.head?.nextnodelist.head

因此,更改内存地址不会影响当前内存地址的位置。list.headlist.head?.nextnode

示例:A -> B -> C ( 这是从LinkedList)

  • 首先,指向内存 Alist.head

  • 然后,指向内存 Anode

  • 然后,指向内存 B,即 。list.headlist.head?.next

  • 所以在内存 A 上根本没有改变。node

评论

0赞 CodeBoxRoll 9/26/2022
谢谢!是的,现在很有意义。如果两个对象共享相同的引用,并且对象在内存中的值发生更改,则两者都将更改。但是,如果其中一个对象将其引用重新分配给内存中的不同位置,则它们将不会共享相同的值