Обновление старого кода, что такое Array (_unsafeUninitializedCapacity: 1024, initializingWith: 0) - PullRequest
0 голосов
/ 08 ноября 2019

Я никогда раньше не сталкивался с этим API:

var a: [Number] = Array(_unsafeUninitializedCapacity: 1024, initializingWith: 0)

Кажется, что это просто:

var a: [Number] = Array(repeating: 0, count: 1024)

Однако я научился никогда не доверять своим внутренним чувствамSwift. Кто-нибудь знаком с этим API и может сообщить мне, выполняет ли моя конверсия то же самое?

1 Ответ

1 голос
/ 08 ноября 2019

Это почти, но не совсем то же самое (хотя ваш синтаксис кажется неправильным на первом).

Сначала краткое описание того, как память выделяется для массивов. Обычно указатель на первый элемент массива, а затем каждое значение занимает последовательные слоты памяти. Массив размером 4 с 4 выделенными слотами памяти может занимать, например, слоты 100 -> 103 памяти. Если бы мы добавили 5-й элемент, нам пришлось бы изменить указатель на новый начальный слот памяти с большей емкостью, затем скопировать все элементы в исходном массиве, а затем добавить новый элемент. Это может стать неэффективным, если мы будем продолжать переполнять память массива (хотя современные телефоны могут легко справиться с этим).

Первый, Array(_unsafeUninitializedCapacity:initializingWith:) - это инициализатор, который дает вам доступ к неинициализированномуслоты памяти также. Но в основном это говорит о том, что нужно выделить достаточно памяти для 1024 записей, а initializeWith - это возможность заполнить некоторые из них, когда вы создаете массив.

Вы можете использовать его следующим образом:

var myArray = Array<Int>(unsafeUninitializedCapacity: 10) { buffer, initializedCount in
    for x in 1..<5 {
        buffer[x] = x
    }
    buffer[0] = 10
    initializedCount = 5
}

, который будет возвращать массив: [10, 1, 2, 3, 4]

buffer дает вам доступ ко ВСЕЙ памятимассив (его inout, поэтому редактирование в закрытии напрямую его меняет). Тогда initializedCount - это еще одно, казалось бы, сохраненное значение, которое, похоже, похоже на то, что оно, вероятно, используется для предоставления O (1) доступа к array.count и / или другим вещам, документы требуют, чтобы это значение было равно фактическим элементам, которые вы заполнили во время закрытия.

Второй, Array(repeating: 0, count: 1024) также создает и заполняет индексы массива. Я понятия не имею, как выбрать распределение памяти, если оно не указано, но есть основания полагать, что если вы не укажете, сколько слотов вы планируете использовать, Apple добавляет некоторую буферную комнату, чтобы не пришлось копировать все эти 1024 элемента, если мы добавимдругой, так что это может быть эквивалентно чему-то вроде:

Array(_unsafeUninitializedCapacity: XXX, initializingWith: "0 for the first 1024 slots")

, где XXX> 1024.

Таким образом, в то время как вы можете получить массив с таким же количеством нулей ... в ниткепесчаный мир памяти, если вы попытаетесь добавить новый элемент к первому, он переполнится, и вам придется выполнить весь процесс копирования.

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

На практике, если вы не делаете что-то ... вовлеченное ... вы, вероятно, могли бы использовать что-то вроде: https://developer.apple.com/documentation/swift/array/1538966-reservecapacity, если вы хотите оптимизировать память, а затем выполнять все операции с массивами, зная, что вы не переполнитесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...