Как сказано в заголовке, я пытался доказать себе, что COW (копирование при записи) поддерживается для String в Swift. Но не могу найти доказательства. Я доказал COW на массиве и словаре, попробовав следующие коды:
func address(of object: UnsafeRawPointer) -> String {
let addr = Int(bitPattern: object)
return String(format: "%p", addr)
}
var xArray = [20, 30, 40, 50, 60]
var yArray = xArray
// These two addresses were the same
address(of: xArray)
address(of: yArray)
yArray[0] = 200
// The address of yArray got changed
address(of: yArray)
Но для типа String это не сработало.
var xString = "Hello World"
var yString = xString
// These two addresses were different
address(of: xString)
address(of: yString)
И я выгрузил тестовую функцию из официального репозитория кода Swift.
func _rawIdentifier(s: String) -> (UInt, UInt) {
let tripe = unsafeBitCast(s, to: (UInt, UInt, UInt).self)
let minusCount = (tripe.0, tripe.2)
return minusCount
}
Но эта функция, похоже, передает только фактическое значение, указанное на адрес, а не на него. Таким образом, две разные строковые переменные с одинаковым значением будут иметь один и тот же rawIdentifier. До сих пор не могу доказать мне COW.
var xString = "Hello World"
var yString = "Hello" + " World"
// These two rawIdentifiers were the same
_rawIdentifier(s: xString)
_rawIdentifier(s: yString)
Так как же COW работает со строковым типом в Swift?
"Hello" + " World"
складывается в"Hello World"
. Вы также можете сделатьvar yString = "Hello"; yString += " World"
, чтобы заметить разницу (в этом случае буфер также получит владельца, поскольку теперь он распределяется динамически, а не статически) - person Hamish   schedule 14.10.2017_rawIdentifier
: использование обходовunsafeBitCast
сохраняет операции подсчета, поэтому вполне возможно, что вы будете смотреть на оборванные указатели (т. е. строковый буфер освобождается, пока вы все еще смотрите на строковое значение) — пытаясь разыменовать тогда будет неопределенное поведение. В коде, из которого вы это взяли, вызывающие использовали_fixLifetime
, чтобы гарантировать, что этого не произойдет. Вы также можете использоватьwithExtendedLifetime(_:_:)
, чтобы убедиться в этом (или использоватьUnsafeMutablePointer
и перепривязать память). - person Hamish   schedule 14.10.2017_rawIdentifier()
не разыменовывает указатель или делает? - person Martin R   schedule 14.10.2017UnsafePointer
s, а затем пытаться проверить указатели). Это было скорее заблаговременное предупреждение :) - person Hamish   schedule 14.10.2017