NSMutableString是如何工作的?

4
我知道所有的NSString实例都是不可变的。如果你给一个字符串赋新值,那么新的内存地址将被寻址,旧的字符串将会丢失。
但是如果你使用NSMutableString,那么无论你做什么,这个字符串始终会保持它在内存中相同的地址。
我想知道这是如何实现的。使用replaceCharactersInRange等方法,我甚至可以向字符串中添加更多的字符,因此需要更多的内存空间。那么跟随字符串的其他对象会发生什么?它们是否都被重新定位并放置在内存的其他位置?我认为不是这样的。但真正发生了什么呢?
2个回答

11
我知道所有的NSString实例都是不可变的。如果你给一个新值,就会寻址新的内存,旧的字符串就会丢失。
这不是可变性的工作方式,也不是NSString引用的工作方式,也不是指针的工作方式。
一个指向对象的指针——NSString *a;声明了一个指向对象的变量a——仅仅是保存了对象在内存中的地址。实际对象通常是一个分配在堆内存中包含实际对象本身的内存。
在这些术语下,在运行时,以下没有任何区别:
NSString *a;
NSMutableString *b;
两者都是对于某个内存分配的地址的引用。唯一的区别在于编译时,编译器会以不同方式处理b而不会在你调用b时发出警告(但是调用a时会发出警告),比如使用NSMutableString方法。
至于NSMutableString的实现原理,它内部包含一个缓冲区(或多个缓冲区——这是实现细节),用来存储字符串数据。当您调用一个修改字符串内容的方法时,可变字符串将根据需要重新分配其内部存储空间以包含新数据。
对象不会在内存中移动。一旦分配,分配将永远不会移动——对象或分配的地址永远不会改变。唯一的半例外是当您使用像realloc()这样的函数时可能会返回不同的地址。但实际上这只是free(); malloc(); memcpy();的序列。
我建议您重新阅读Objective-C编程指南或者一本C语言编程手册。

0

NSMutableString的工作方式与C++ std::string类似。我不知道它们的确切工作方式,但有两种流行的方法:

连接

您创建一个具有两个变量的结构体。一个是char类型,另一个是指针类型。 当添加新的字符(或更多字符)时,您创建结构体的新实例,并将地址添加到字符串的最后一个结构体实例中。这样,您就拥有了一堆带有指向下一个结构体的指针的结构体。

复制和添加

这是大多数新手会采用的方式。虽然不是最糟糕的,但可能是最慢的。 您保存一个“普通”的不可变字符串。如果添加了新字符,则在内存中分配一个大小为旧字符串+1的区域,复制旧字符串并连接新字符。这是一种非常简单的方法,不是吗? 更高级的版本是使用大小+50创建新字符串,只需在末尾添加字符和新的null,不要忘记覆盖旧的null。这样对于经常更改的字符串更有效率。

正如我之前所说,我不知道std::string或NSMutableString如何处理此问题。但这些是最常见的方法。


NSMutableString和C++的std::string除了都是字符串容器之外,实际上并没有太多相似之处。 - bbum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接