Вызывает ли тип значения, возвращаемый функцией, функцию копирования при записи при изменении? - PullRequest
3 голосов
/ 26 марта 2020

Простой вопрос, но я не уверен, как проверить. Всегда ли тип значения, возвращаемый функцией, вызывает копирование при записи при изменении, или вы изменяете точно такой же экземпляр, который был создан внутри?

Например, я знаю, что это не инициирует копирование при записи, так как вы изменяете объект прямо при его создании.

struct Foo{
    var value:String = "Initial"
}

var a = Foo()
a.value = "Changed" // <- This does *not* make a copy of Foo

Однако здесь я не уверен, является ли оригинальное значение таким образом осиротевшим

func fooFactory() -> Foo {
    return Foo()
}

var b = fooFactory()
b.value = "Changed again" // <- Does this trigger a copy-on-write in the compiler?

Причина этого вопроса в том, что у нас есть очень тяжелые структуры, которые по причинам, в которые я не могу войти, не могут быть классами, и наши фабричные методы для этих структур делают очень много первоначальной конфигурации, затем потребители делают окончательную настройку после того, как они возвращаются с завода.

Я пытаюсь понять, действительно ли мы создаем тонны копий, которые мы, по сути, мгновенно выбрасываем в тот момент, когда они покидают завод.

Обновление:

Вот мой тест, который показывает, что да, копия сделана накануне выхода n перед тем, как вы его измените (проверьте «c» ниже). Изменение этого возвращаемого значения (test 'd'), однако, не создает дополнительную копию, так как копия уже была сделана после возврата из функции.

Тем не менее, я не уверен на 100%, что это действительный / точный тест, поэтому любая обратная связь будет принята с благодарностью.

struct Foo {
    var value:Int = 0
}

var lastCheckedPointer:UnsafePointer<Foo>?

func printAddress(_ test: CustomStringConvertible, _ pointer:UnsafePointer<Foo>){

    let observation = lastCheckedPointer.map{
        $0 == pointer
            ? "Same instance"
            : "Copy created"
    } ?? "Initial instance"

    print("Test \(test): \(pointer) - \(observation)")

    lastCheckedPointer = pointer
}

func makeFoo() -> Foo {

    var insideFoo = Foo()
    printAddress("a", &insideFoo)

    insideFoo.value = 1
    printAddress("b", &insideFoo)

    return insideFoo
}

var foo = makeFoo()
printAddress("c", &foo)

foo.value = 2
printAddress("d", &foo)

foo.value = 3
printAddress("e", &foo)

var foo2 = foo
foo2.value = 4
printAddress("f", &foo2)

Результаты:

Test a: 0x00007ffc735598d8 - Initial instance
Test b: 0x00007ffc735598d8 - Same instance
Test c: 0x000055cbfb6da1f0 - Copy created <-- This is the returned value
Test d: 0x000055cbfb6da1f0 - Same instance
Test e: 0x000055cbfb6da1f0 - Same instance
Test f: 0x000055cbfb6da1f8 - Copy created
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...