Copy-on-write conserva la semántica de valor y retrasa la copia del almacenamiento. Antes de modificar almacenamiento compartido, sepáralo; si solo tiene un propietario, modifícalo directamente. No todos los struct implementan esto automáticamente.
Mecanismo y decisión de diseño
La semántica de una colección estándar y las responsabilidades de un almacenamiento propio son distintas. Aquí una clase privada contiene un array de enteros y los métodos mutables consultan isKnownUniquelyReferenced. Todas las rutas de modificación deben mantener esa disciplina. Fuente primaria
Código reproducible
Tras asignar IntBuffer, comprobamos por identidad que ambos valores comparten Storage. Añadir 3 a la copia debe separarlo y preservar el array original. Añadir 4 después no debe separarlo otra vez, porque la copia ya posee Storage de forma única.
Este ejemplo independiente se ejecutó el 2026-10-23 con Apple Swift 6.4 para arm64 macOS, en modo de lenguaje Swift 6. No necesita red ni paquetes adicionales.
Descargar el archivo Swift completo
Ejecuta el comando en la carpeta de descarga. Las precondiciones detienen la ejecución si falla una comprobación. No uses -Ounchecked: elimina estas comprobaciones.
swift -swift-version 6 swift-copy-on-write-prototype-pattern.swift
struct IntBuffer {
private final class Storage {
var values: [Int]
init(_ values: [Int]) { self.values = values }
}
private var storage: Storage
private(set) var detachments = 0
init(_ values: [Int]) { storage = Storage(values) }
var values: [Int] { storage.values }
func sharesStorage(with other: IntBuffer) -> Bool {
storage === other.storage
}
mutating func append(_ value: Int) {
if !isKnownUniquelyReferenced(&storage) {
storage = Storage(storage.values)
detachments += 1
}
storage.values.append(value)
}
}
let original = IntBuffer([1, 2])
var copy = original
precondition(copy.sharesStorage(with: original))
copy.append(3)
precondition(!copy.sharesStorage(with: original))
precondition(original.values == [1, 2] && copy.values == [1, 2, 3])
copy.append(4)
precondition(copy.detachments == 1 && copy.values == [1, 2, 3, 4])
print("shared-before=true shared-after=false detachments=1 original=[1,2] copy=[1,2,3,4]")
Salida registrada e interpretación
shared-before=true shared-after=false detachments=1 original=[1,2] copy=[1,2,3,4]
detachments=1 cuenta una separación de nuestro contenedor Storage. El original queda en [1,2] y la copia en [1,2,3,4]. No mide asignaciones del búfer interno de Array, que puede usar su propia implementación CoW.
Alcance y limitaciones
Es un ejemplo didáctico de flujo único, no una colección segura entre hilos. Comprobar unicidad no sincroniza accesos. Un array de instancias de clase tampoco clona profundamente sus elementos: los tipos de valor no eliminan todos los usos del patrón prototipo.
Qué comprobar después
Distingue los datos que requieren copias independientes de los que pueden compartirse. Mide el rendimiento con cargas reales y prioriza colecciones estándar salvo necesidad concreta. El experimento class frente a struct muestra referencias internas compartidas.
Fuentes y verificación
- Swift Standard Library: isKnownUniquelyReferencedSwift.org · Documentación oficial · Consultado 23 de octubre de 2026Respalda: Fuente del contrato de implementación y de la explicación. La salida se comprobó por separado con el experimento incluido aquí.

