复制命令 - 深或浅副本?

时间:2017-03-31 16:18:22

标签: swift swift3 copy

当我在iOS(swift / objective c)中使用copy命令复制对象时,这是浅拷贝还是深拷贝?

var str = "Hello, playground"
var copyStr = str.copy()

var originalArray = [1, 2, 3, 4] as NSArray
var copyArray = originalArray.copy()

withUnsafePointer(to: &originalArray) {
    print(" originall address: \($0)")
}

withUnsafePointer(to: &copyArray) {
    print(" copy address: \($0)")
}

请帮我看一下上面的行,这是一份深拷贝还是浅拷贝?

  

问题是,目标c中的这种行为向我展示了同样的情况   字符串和数组都是浅拷贝和swift3   它向我展示了不同的地址,即深拷贝

2 个答案:

答案 0 :(得分:3)

let obj1 = Object(value: 1) let obj2 = Object(value: 2) let obj3 = Object(value: 3) let originalArray = [obj1, obj2, obj3] as NSArray let copyArray = originalArray.copy() as! NSArray print(String(format: "original address: %p", originalArray)) for obj in originalArray { print(String(format: " %p", obj as! Object)) } print(String(format: "copy address: %p", copyArray)) for obj in copyArray { print(String(format: " %p", obj as! Object)) } 执行浅拷贝(集合的副本,但不复制数组中的对象)。 E.g。

NSNumber

注意,我使用NSStringoriginal address: 0x618000044920 0x6180000277e0 0x618000027f00 0x618000027ea0 copy address: 0x618000044920 0x6180000277e0 0x618000027f00 0x618000027ea0 以外的对象,因为这些对象可能会使地址误导。

这两个数组的成员对象指向相同的对象(即浅拷贝)。

NSArray

事实上,正如您所看到的,因为它是一个不可变的NSMutableArray,它似乎优化了这个副本实际返回相同数组实例的地方。如果您使用可变数组NSArray(array:copyItems:),那么您会看到返回的两个唯一数组,但是它们仍会指向相同的对象集合。

但是,如果对true使用copyItemslet copyArray = NSArray(array: originalArray as! [Any], copyItems: true) ,则会得到两个唯一的数组,其中包含每个成员对象的唯一副本:

original address: 0x618000059e60
    0x618000027ae0
    0x618000028340
    0x618000028280
copy address: 0x61800005ba20
    0x618000028800
    0x618000028aa0
    0x618000028400

产生一个深层副本(两个唯一的数组,其中复制了各个成员对象,它们也有唯一的地址):

init(array:copyItems:)

copy(with:​)查看true,其中包含:

  

flag方法执行浅拷贝。如果您有任意深度的集合,则init(array:copyItems:)参数[{1}}]的false传递将执行表面下第一级的不可变副本。如果您通过Array,则第一级的可变性不受影响。在任何一种情况下,所有更深层次的可变性都不会受到影响。

就个人而言,如果编写Swift,我通常会使用DictionaryNSArray值类型,而不是旧的NSDictionary std::map<std::string, stockDictType::iterator, Comparator> stocksTicker(Comparator(stocksDict)); 类型。

答案 1 :(得分:0)

Swift中的字符串是值类型。对于所有值类型,将创建现有String值的新副本。

来自Apple Document。

  

Swift的默认复制String行为确保了当一个函数   或者方法传递给你一个String值,显然你拥有它   精确的字符串值,无论它来自何处。你可以   确信您传递的字符串不会被修改,除非   你自己修改它。

希望这有帮助