string - 将 UnsafeMutablePointer 与 String 或 Character 类型一起使用时出现不一致

标签 string swift pointers generics unsafe-pointers

我目前正在尝试实现我自己的 DynamicArray Swift 中的数据类型。为此,我稍微使用了指针。作为我的root我正在使用 UnsafeMutablePointer通用类型 T :

struct DynamicArray<T> {
    private var root: UnsafeMutablePointer<T> = nil
    private var capacity = 0 {
        didSet {
            //...
        }
    }

    //...

    init(capacity: Int) {
        root = UnsafeMutablePointer<T>.alloc(capacity)
        self.capacity = capacity
    }

    init(count: Int, repeatedValue: T) {
        self.init(capacity: count)

        for index in 0..<count {
            (root + index).memory = repeatedValue
        }
        self.count = count
}

    //...
}

现在如您所见,我还实现了 capacity属性告诉我当前为 root 分配了多少内存。 。因此,我们可以创建 DynamicArray 的一个实例。使用init(capacity:)初始化程序,分配适当的内存量,并设置 capacity属性(property)。
但后来我也实现了 init(count:repeatedValue:)初始化程序,它首先使用 init(capacity: count) 分配所需的内存。然后,它将该部分内存中的每个段设置为 repeatedValue .

使用 init(count:repeatedValue:) 时具有数字类型的初始值设定项,如 Int , Double ,或Float它工作得很好。然后使用 Character ,或String虽然它崩溃了。虽然它不会持续崩溃,但有时确实有效,如 here 所示。 ,通过编译几次。

var a = DynamicArray<Character>(count: 5, repeatedValue: "A")
println(a.description) //prints [A, A, A, A, A]
//crashes most of the time

var b = DynamicArray<Int>(count: 5, repeatedValue: 1)
println(a.description) //prints [1, 1, 1, 1, 1]
//works consistently

为什么会发生这种情况?和String有关系吗?和Character保存不同长度的值?


更新#1:

现在@AirspeedVelocity用init(count:repeatedValue:)解决了这个问题。 DynamicArray但包含另一个初始化程序,它最初的工作方式与 init(count:repeatedValue:) 类似。 。我将其更改为工作,如 @AirspeedVelocity 所描述的 init(count:repeatedValue:)不过:

init<C: CollectionType where C.Generator.Element == T, C.Index.Distance == Int>(collection: C) {
    let collectionCount = countElements(collection)
    self.init(capacity: collectionCount)
    
    root.initializeFrom(collection)
    count = collectionCount
}

我正在使用initializeFrom(source:)方法如所述here 。自从 collection符合CollectionType它应该工作正常。
我现在收到此错误:

<stdin>:144:29: error: missing argument for parameter 'count' in call
    root.initializeFrom(collection)
                        ^

这又是一个误导性的错误消息吗?

最佳答案

是的,这对于整数等基本惰性类型可能不会崩溃,但对于字符串或数组会崩溃,因为它们更复杂并且在创建/销毁时为自己分配内存。

崩溃的原因是 UnsafeMutablePointer 内存在使用之前需要初始化(同样,在释放之前需要使用 destroy 取消初始化)。

因此,您应该使用 initialize 方法,而不是分配给 memory 属性:

for index in 0..<count {
    (root + index).initialize(repeatedValue)
}

由于从另一个值集合进行初始化非常常见,因此还有另一个版本的 initialize 接受一个值。您可以将其与另一个辅助结构 Repeat 结合使用,它是重复多次的相同值的集合:

init(count: Int, repeatedValue: T) {
    self.init(capacity: count)
    root.initializeFrom(Repeat(count: count, repeatedValue: repeatedValue))
    self.count = count
}

但是,您还需要注意的是,此代码目前不可避免地会泄漏内存。原因是,在销毁 DynamicArray 结构之前,您需要在某个时刻销毁内容并dealloc指向的内存,否则你会泄漏。由于在结构中不能有 deinit,而只能在类中,所以这不可能自动完成(假设您不希望数组的用户自己手动执行此操作)在它超出范围之前)。

此外,如果您想通过写时复制来实现值语义(如 ArrayString),您还需要一种方法来检测是否您的内部缓冲区被多次引用。查看 ManagedBufferPointer 以查看为您处理此问题的类。

关于string - 将 UnsafeMutablePointer 与 String 或 Character 类型一起使用时出现不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28767513/

相关文章:

ios - 如何在 swift 3.0 中从 UITableViewCell 按钮单击添加弹出框转场?

ios - 在 viewDidLoad() 中访问 UserDefaults

ios - GMS map View 始终显示欧洲

c - 这段代码中*first 打印的是什么?

python - 剥离 numpy 数组中的空格

c++ - 将字符串转换为 double 时出现算术错误

php - 如何获取字符串中某个单词前后的所有内容

字符指针 : Creating dynamic string array, 赋值并传递给其他函数和其他小家伙 - C

c++ - malloc 和 new 是否返回一个 int 对齐的地址?

c - 获取包含链接列表的功能以在C中正常工作