tl; dr : Dlaczego, gdy tablica jest tworzona wraz z wartościami początkowymi, wartości są od razu inicjowane od razu, ale wypełnianie wartości tablicy po utworzeniu tablicy wytwarza różne zachowanie?


Uczę się Swift po JavaScript, który ma GC, więc koncepcje łuku i deicjalizacji są dla mnie nieco nowicjusze. Aby zrozumieć głębiej, napisałem następujący kod, na podstawie Przykład z Oficjalna dokumentacja:

// definitions; see the next two snippets for usage
class Bank {
    static var coins: Int = 100 {
        didSet {
            let diff = coins - oldValue
            let sign = diff < 0 ? "-" : "+"

            print("Bank: \(oldValue) \(sign) \(diff.magnitude) = \(coins)")
        }
    }

    static func give(_ amount: Int, to user: User) {
        guard amount <= coins else {
            print("[ERROR] The bank does not have enough coins; requested \(amount - coins) more coins than available")
            return
        }

        user.purse += amount
        coins -= amount
    }

    static func take(_ amount: Int, from user: User) {
        user.purse -= amount
        coins += amount
    }
}

class User {
    private static var count = 0

    let id: Int

    var purse = 0

    init() {
        User.count += 1

        id = User.count
    }

    deinit {
        print("User #\(id) perished")

        Bank.take(purse, from: self)
    }
}

Gdy tworzę tablicę z istniejącymi instancjami użytkownika ({x0}}), inicjalizację dzieje się zaraz po przypisaniu do nil (array[0] = nil):

var users: [User?] = [
    User(),
    User(),
]

Bank.give(90, to: users[0]!)
users[0] = nil
Bank.give(50, to: users[1]!) // works

//  Bank: 100 - 90 = 10
//  User #1 perished
//  Bank: 10 + 90 = 100
//  Bank: 100 - 50 = 50

... Ale kiedy po raz pierwszy utworzam pustą tablicę, a następnie wypełniam go wartościami (array = []; array[0] = value; array[1] = value), odintualizacją dzieje się w niektórych przypadkowych punktach później:

var users = [User?](repeating: nil, count: 2)

users[0] = User()
users[1] = User()

Bank.give(90, to: users[0]!)
users[0] = nil
Bank.give(50, to: users[1]!) // fails

//  Bank: 100 - 90 = 10
//  [ERROR] The bank does not have enough coins; requested 40 more coins than available
//  User #1 perished
//  Bank: 10 + 90 = 100

Jaka jest różnica z punktu widzenia kompilatora? A jaka jest uzasadnienie tej różnicy?

0
Dima Parzhitsky 10 październik 2020, 17:24

1 odpowiedź

Najlepsza odpowiedź

TL; DR nie polegają na terminie dealokacji / deicjalizacji.

Dotyczącym się dokładnie, gdy DealLocation, a zatem deicjalizację, która występuje natychmiast przed, dzieje się procesem nierywialnym.

Gwintowanie (i prawie każda aplikacja jest multi-gwintowana, nawet jeśli nie jest bezpośrednio używać gwintowania), skompilatorów, przekazujących wartości wokół itp. Wszystkie przyczynia się do zaciemnienia dokładnie, gdy ostatnie odniesienie do obiektu zniknie.

Na szczycie tego Swift Playground sam może utrzymywać niewiałe odniesienia do obiektów z powodu sposobu, w jaki działa, co wydaje się, że wydaje się tutaj dzieje. Umieszczenie kodu w aplikacji Swift Line Line działa dla nas, Ale YMMV!

HTH

0
CRD 11 październik 2020, 21:37