Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift withUnsafePointer和Unmanaged.passUnretained有什么区别_Swift_Memory_Unsafe Pointers - Fatal编程技术网

Swift withUnsafePointer和Unmanaged.passUnretained有什么区别

Swift withUnsafePointer和Unmanaged.passUnretained有什么区别,swift,memory,unsafe-pointers,Swift,Memory,Unsafe Pointers,我想看看当我将新字符串附加到原始字符串时,与目标C相比,swift字符串结构指针是如何变化的。对于目标C,我使用以下代码: NSMutableString *st1 = [[NSMutableString alloc] initWithString:@"123"]; [st1 appendString:@"456"]; 在Objective C中,st1字符串对象在内部发生变化(添加456并变为123456),但st1指针向左移动并指向同一对象。在Swift中,由于字符串是不可变的,所以var

我想看看当我将新字符串附加到原始字符串时,与目标C相比,swift字符串结构指针是如何变化的。对于目标C,我使用以下代码:

NSMutableString *st1 = [[NSMutableString alloc] initWithString:@"123"];
[st1 appendString:@"456"];
在Objective C中,st1字符串对象在内部发生变化(添加456并变为123456),但st1指针向左移动并指向同一对象。在Swift中,由于字符串是不可变的,所以var st1必须在加法后更改其地址,因为它将保存另一个字符串,其中包含my strings summ(123456)。这些都对吗

这是我的swift测试操场代码:

import Cocoa

var str = "123"
withUnsafePointer(to: &str) { print($0) }
str += "456"
withUnsafePointer(to: &str) { print($0) }

var str2 = "123"
print(Unmanaged<AnyObject>.passUnretained(str2 as AnyObject).toOpaque())
str2 += "456"
print(Unmanaged<AnyObject>.passUnretained(str2 as AnyObject).toOpaque())

为什么我在使用withUnsafePointer时得到相同的指针?为什么使用Unmanaged.passUnretained时会得到不同的指针?为什么从这个方法接收到的指针完全不同?

为了更好地解释您看到的行为,我们可以查看
字符串
源代码

因此,
String
只是一个包装器,它围绕着一种叫做
\u StringCore
的类型。我们可以找到它的定义。以下是相关部分:

public struct _StringCore {
  //...

  public var _baseAddress: UnsafeMutableRawPointer?
  var _countAndFlags: UInt

  //...
}
如您所见,
\u StringCore
不直接包含存储字符串内容的内存缓冲区。相反,它通过
unsafemeutablerawpointer
在外部引用它

第一次声明
str
时,堆栈上的地址
0x000000010e228c40
为它提供了一些内存。当您更改
str
时,实际上对该
字符串的位置没有任何影响。相反,您导致
字符串的
\u核心
\u基地址
发生更改<代码>数组
的工作方式非常相似。这也是字符串写时复制行为的实现方式

对于
非托管的
行为,
str2作为任何对象
创建了一个
str2
的副本,因此您最终创建了两个不同的副本,因此 印刷品的地址是

public struct String {
  /// Creates an empty string.
  public init() {
    _core = _StringCore()
  }

  public // @testable
  init(_ _core: _StringCore) {
    self._core = _core
  }

  public // @testable
  var _core: _StringCore
}
public struct _StringCore {
  //...

  public var _baseAddress: UnsafeMutableRawPointer?
  var _countAndFlags: UInt

  //...
}