NSString指针:学习后的理论问题

发布于 2024-12-03 17:02:29 字数 1344 浏览 2 评论 0 原文

我对 NSString 指针有疑问。我想弄清楚这一点,并实际上尝试创建一个理论,以基于从当时网络检索到的多个信息来获得充分的理解。请相信我,我并没有偷懒,我实际上读了很多书,但仍然留下了不确定性和疑问。您能否确认/否认好/错,我已经提出了额外的问题和疑问,用(?)表示。

开始了: 如果我考虑这个非常基本的例子:

NSString *sPointer = [[NSString alloc]initWithString:@"This is a pointer"]; 
[sPointer release];

我的出发点是:编译器为指针类型保留 RAM 内存,并且该内存(也有自己的地址)包含存储另一个变量的内存的内存地址(十六进制 - 二进制) (它指向的地方)。实际的指针将占用大约 2 个字节:

1)首先是一些一般性问题 - 不一定与目标 C 有关。有关 NSString 指针的实际问题将在第 2 点中出现。 字符串是“字符串”,其中 1 个字符占用固定量的内存空间,假设为 2 个字节。 这自动意味着字符串变量占用的内存大小由字符串的长度定义。 然后我在维基百科上读到了这个: “在现代字节寻址计算机中,每个地址标识存储的单个字节;太大而无法存储在单个字节中的数据可能驻留在占用一系列连续地址的多个字节中。” 所以在这种情况下,字符串值实际上由多个地址包含,而不是由单个 1 包含(这已经与我在各处读到的不同)(?)。 1个指针中包含的多个地址实际上是如何实现的?指针也会被分成多个地址吗? 您知道计算机中的哪个组件实际上识别并分配实际的地址“代码”吗?

现在是我的实际问题;

2)在我的示例中,代码做了两件事:

  • 它创建一个指向存储字符串变量的地址的指针。
  • 它实际上还保存了实际的“字符串变量”:@“这是一个指针”,因为否则就没有什么可以指向的;

好的,我的问题;我想知道当你释放指针时到底会发生什么[sPointer release];您实际上是释放指针(包含地址),还是也从内存中释放实际的“字符串变量”? 我了解到,当您删除引用时,存储实际变量的内存将在编译器需要内存时被覆盖,因此当时不需要清除它。这是错误的吗? 如果它是正确的,为什么他们说出于性能原因释放 NSString 指针非常重要,如果你只是释放基本上只包含几个字节的指针?或者我错了,存储实际变量的内存实际上也随着“释放”消息立即清除了吗?

最后还有:原始数据类型不会被释放,但它们在声明时“确实”占用了内存空间(但不超过公共指针)。实际上我们为什么不应该释放它们呢?是什么阻止我们做这样的事情:int i = 5,然后是 [i release]?;

抱歉 - 一次性问了很多问题!在实践中,我从来没有遇到过问题,但在理论上,我也真的很想完全理解它——而且我希望我不是唯一一个。我们可以讨论这个话题吗? 谢谢您,抱歉打扰了!

I have questions about the NSString pointer. I wanted to get to the bottom of this and actually tried to create a theory to obtain full understanding based on multiple information retrieved from then net. Please believe me when I say that I have not been lazy, and I actually read a lot, but I was still left with uncertainties and questions. Can you please confirm / deny when good / wrong, and I've put additional questions and doubts which are indicated by (?).

Here we go:
If I consider this very basic example:

NSString *sPointer = [[NSString alloc]initWithString:@"This is a pointer"]; 
[sPointer release];

My starting point was: The compiler reserves RAM memory for a pointer type and this memory (which also has an own address) contains the memory address (hexadecimal - binary) of the memory where another variable is stored (where it points to). The actual pointer would take up about 2 bytes:

1) First some general issue - not necessarily linked to objective C. The actual questions about the NSString pointer will come in point 2.
A string is a "string of characters", where 1 character takes a fixed amount of memory space, let's say 2 bytes.
This automatically means that the memory size occupied by a string variable is defined by the length of the character string.
Then I read this on Wikipedia:
"In modern byte-addressable computers, each address identifies a single byte of storage; data too large to be stored in a single byte may reside in multiple bytes occupying a sequence of consecutive addresses. "
So in this case, the string value is actually contained by multiple addresses and not by a single 1 (this already differs from what I read everywhere) (?).
How are these multiple addresses contained in 1 pointer in reality? Will the pointer be divided into multiple addresses as well?
Do you know what component in a computer actually identifies and assigns the actual address "codes"?

And now my actual questions;

2) In my example, the code does 2 things:

  • It creates a pointer to the address where the string variable is stored.
  • It also actually saves the actual "String variable": @"This is a pointer", because otherwise there would be nothing to point to;

OK, my question; I wondered what really happens when you release the pointer [sPointer release]; are you actually releasing the pointer (containing the address), or are you also releasing the actual "string variable" from memory as well?
I have learned that when you delete the reference, the memory where the actual variable is stored will just be overwritten at the time the compiler needs memory so it does not need to be cleared at that time. Is this wrong?
If it is correct, why do they say that it's really important to release the NSString pointer for performance reasons, if you just release the pointer which will basically contain only a few bytes? Or am I wrong, and is the memory where the actual variable is stored in fact also cleared at once with the "release" message?

And finally also: primitive datatypes are not released, but they "do" take memory space at the moment of declaration (but not more than a common pointer). Why shouldn't we release them in fact? What prevents us from doing something like: int i = 5, followed by [i release]?;

I'm sorry - a lot of questions in 1 time! In practice, I never had problems with it, but in theory, I also really want to fully understand it - and I hope that I'm not the only one. Can we discuss the topic?
Thank you and sorry for the bother!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

孤者何惧 2024-12-10 17:02:29

也许我错了,但我昨天刚读到指针通常占用 4 个字节。这没有回答你的任何问题,但你似乎对此很感兴趣,所以我想我会提到它。

我认为您混淆的根源在于您将原语与 Objective-C 类混淆了。 Objective-C 类(或者准确地说是对象,类的实例)可以接受消息(类似于其他语言中的方法调用)。 retain 就是这样的一条消息。这就是为什么 Objective-C NSString 对象可以接收 retain 消息,但不能接收像整数这样的基元。我认为这是你的另一个困惑。 retainrelease 等不是 Objective-C 语言结构,它们是发送给对象的实际消息(认为是方法)。这就是为什么它们适用于 Objective-C 对象,但不适用于整数和浮点数等基元。

另一个类似的困惑是,您所读到的有关字符串存储方式的内容更多地与 C 样式字符串有关,例如 char *name = "john"。但是,当您创建一个指向 NSString 的指针时,它指向一个 NSString 实例,它本身决定如何处理存储实际的字符串字节/人物。这可能与 C 字符串的存储方式相同,也可能不同。

太大而无法存储在单个字节中的数据可能驻留在占用一系列连续地址的多个字节中。 " 所以在这种情况下,字符串值实际上是由多个地址包含的,而不是由单个 1 包含的(这已经与我在各处读到的不同)(?)。这些多个地址实际上是如何包含在 1 个指针中的?

在 C 中例如,指针将指向字符串中第一个字符的地址。

好的,我的问题;我想知道当你释放指针时到底会发生什么[sPointer release];您实际上是释放指针(包含地址),还是也从内存中释放实际的“字符串变量”?

您正在将 release 消息发送到 NSString 实例/对象。需要注意这一点,以避免进一步混淆。您不是对指针本身进行操作,而是对指针所指向的对象进行操作,即 NSString 对象。所以你没有释放指针本身。在向对象发送release方法后,如果它的引用计数达到0,那么它将通过释放它存储的所有内容来处理自身的释放,我想其中包括实际的字符串。

如果这是正确的,为什么他们说出于性能原因释放 NSString 指针非常重要,如果你只是释放基本上只包含几个字节的指针?

所以,是的,您实际上是将 release 消息发送到字符串实例,并且它会在必要时处理如何释放自身。如果您只是简单地擦除指针,使其不再指向字符串实例,那么您将不再知道在哪里/如何访问存储在该位置的数据,但它不会使其神奇地消失,程序不会自动知道它可以使用该内存。您暗示的是垃圾收集,简单地说,未使用内存将自动释放以供后续使用。 Objective-C 2.0 确实有垃圾回收功能,但据我所知,iOS 设备上还没有启用它。相反,新版本的 iOS 将支持一项名为 自动引用计数,其中编译器本身负责引用计数。

抱歉,如果我没有回答您的所有问题,您问了很多问题:P 如果我的信息有误,请告诉我!我试图将我的答案限制在我认为我确实知道的范围内。

Maybe I'm wrong but I just read yesterday that pointers usually take 4 bytes. That answers none of your questions but you seem really interested in this so I figured I would mention it.

I think the source of your confusion is that you are confusing primitives with Objective-C classes. Objective-C classes (or objects to be exact, instances of classes) can accept messages (similar to method invocations in other languages). retain is one such message. This is why an Objective-C NSString object can receive the retain message but not a primitive like an integer. I think that's another one of your confusions. retain and release etc. are not Objective-C language constructs, they're actual messages (think methods) you send to objects. That is why they apply to Objective-C objects but not to primitives like integers and floats.

Another similar confusion is that what you read about how strings are stored has more to do with C-style strings, like char *name = "john". However, when you create a pointer to an NSString, that points to an NSString instance, which itself decides how to handle storing the actual string bytes/characters. Which may or not be the same way that C strings are stored.

data too large to be stored in a single byte may reside in multiple bytes occupying a sequence of consecutive addresses. " So in this case, the string value is actually contained by multiple addresses and not by a single 1 (this already differs from what I read everywhere) (?). How are these multiple addresses contained in 1 pointer in reality?

In C for example, the pointer would point to the address of the first character in the string.

OK, my question; I wondered what really happens when you release the pointer [sPointer release]; are you actually releasing the pointer (containing the address), or are you also releasing the actual "string variable" from memory as well?

You are sending the release message to the NSString instance/object. This is important to note to avoid further confusion. You are not acting upon the pointer itself, but upon what the pointer is pointing to, which is the NSString object. So you are not releasing the pointer itself. After sending the object the release method, if its reference count has reached 0, then it will handle deallocating itself by deallocating everything it stores, which I imagine includes the actual character string.

If it is correct, why do they say that it's really important to release the NSString pointer for performance reasons, if you just release the pointer which will basically contain only a few bytes?

So yeah, you're actually sending the release message to the string instance and it handles how to deallocate itself if it has to. If you were to simply erase the pointer so that it no longer points at the string instance, then you simply will no longer know where/how to access the data stored at that location, but it won't make it magically disappear, the program won't automatically know that it can use that memory. What you're hinting at is garbage collection, in which, simply put, unused memory will automatically be freed for subsequent use. Objective-C 2.0 does have garbage collection but as far as I know it's not enabled on iOS devices yet. Instead, the new version of iOS will support a feature known as Automatic Reference Counting in which the compiler itself takes care of reference counting.

Sorry if I didn't answer all of your questions, you asked a ton :P If any of my information is wrong please let me know! I tried to limit my answer to what I felt I did know.

橪书 2024-12-10 17:02:29

“或者我错了,存储实际变量的内存实际上也会随着“释放”消息立即清除吗?”内存没有被清除,而是进入空闲内存池,因此它实际上减少了程序的内存打印。如果您没有释放指针,您将继续“占用”内存,直到耗尽所有可用的虚拟内存,并且不仅会崩溃您的程序,还会导致系统崩溃。

"Or am I wrong, and is the memory where the actual variable is stored in fact also cleared at once with the "release" message?" The memory IS NOT CLEARED, but goes into the free memory pool, so that it does in fact reduce the memory print of the program. If you did not release the pointer you would continue to "hog" memory until you consume all the virtual memory available and crash not only your program but potentiality the system as well.

南城旧梦 2024-12-10 17:02:29

实际上,1个指针中包含的多个地址是如何实现的?
指针也会被分成多个地址吗?你
知道计算机中的哪个组件实际识别并分配
实际地址“代码”?

从程序员的角度来看(请注意这一点),指针本身通常是一个 4 字节数字,表示从内存开始的偏移量(32 位,在 64 位中,您可以拥有最多 8 个字节的地址)。问题是 this 指针指向正在存储的内容的开头,就是这样。

例如,在 C 中,原始字符串使用 NULL (\0) 结尾的字符串来标识字符串何时结束(尝试在 C 上使用非零结尾的字符串执行 printf() ,它将打印内存中的任何内容,直到找到零)。这当然是相当危险的,必须使用诸如 strncpy 之类的函数(注意“n”),指示您应该手动输入从偏移量到结束的字符数。

避免这种情况的一种方法是将已用空间存储在内存地址的开头,例如

struct
{
    int size;
    char *string;
}string;

存储大小以防止出现任何问题。 Objective-C 和许多其他更抽象的语言以自己的方式实现如何处理内存。 NSString* 是一个非常抽象的类,它知道幕后发生的事情,它可能继承了 NSObject 的所有内存管理。

我试图得到的全部要点是指针包含起始地址,您可以从那里逐个字节跳转(或跳转一定大小),请记住您要存储的内容的总长度,以避免做一些令人讨厌的事情,例如溢出堆栈内存(因此,该站点的名称)。

现在,计算机如何提供这些地址完全取决于操作系统,并且您在所有程序中使用的逻辑内存地址与底层实现使用的地址(物理内存地址)有很大不同。通常,您会发现内存存储在称为“帧”的分段单元中,并且使用的帧称为“页面"。物理和逻辑之间的映射是通过“[页表]”2 完成的。

正如您所看到的,该软件几乎可以处理所有事情,但这并不意味着没有硬件支持这一点,例如 TLB,CPU级缓存,保存最近的内存地址以供快速访问。

另外,请对我的回答持保留态度,我已经有一段时间没有研究这些科目了。

好的,我的问题;我想知道当你释放
指针[sPointer释放];你真的释放了指针吗
(包含地址),或者您是否也释放了实际的“字符串
内存中的变量”?我了解到,当你删除
引用,存储实际变量的内存将是
在编译器需要内存时覆盖,因此不需要
到时候就可以清除了。这是错误的吗?如果正确的话为什么
他们说释放 NSString 指针非常重要
出于性能原因,如果您只是释放指针,则会
基本上只包含几个字节?还是我错了,是记忆
实际变量存储的位置实际上也立即清除
“释放”消息?

当你释放时,你只是减少了对象的内存数量。你的意思是当它被释放时(当计数达到零时)会发生什么。

当您dealloc某些东西时,您基本上是在说它所保留的空间现在可以被任何其他请求内存的空间(通过分配)替换。该变量可能仍然指向已释放的空间,这会导致问题(阅读有关悬空指针和泄漏的信息)。

内存可能会被清除,但不能保证

我希望这能消除所有疑虑,因为所有疑虑都源于您对内存释放的困惑。

最后还有:原始数据类型没有发布,但它们“发布”了
在声明时占用内存空间(但不超过
公共指针)。实际上我们为什么不应该释放它们呢?是什么阻止了
我们可以这样做:int i = 5,然后是 [i release]?;

问题是 C 有两个主要的事情(实际上,还有更多): 堆,用于存储通过 alloc(或 C 中的 malloc)请求的内存,并且这些需要被释放。保存局部变量的堆栈会在函数/块结束时死亡(堆栈弹出函数调用)。

在您的示例中,变量 i 已在其范围内本地声明,并且在堆栈中继续。尝试执行 dealloc/free (此外,变量 i 不会响应释放,也不会响应 dealloc,因为它不是对象)将不起作用,因为不是需要释放的内存类型。

我建议您在尝试解决 Objective-C 的功能之前先回到 C,因为很难清楚地了解命令式编程如何与所有漂亮的抽象(如发布和释放)一起工作。

How are these multiple addresses contained in 1 pointer in reality?
Will the pointer be divided into multiple addresses as well? Do you
know what component in a computer actually identifies and assigns the
actual address "codes"?

From the perspective of the programmer (take note of this), the pointer on itself is usually a 4-byte number that represents the offset from start from the memory (32-bits, in 64-bit you can have addresses up to 8 bytes). The thing is that this pointers points to the start of whatever is being stored, and that's it.

In C for example, the original strings used a NULL (\0) terminated strings to identify when a string ended (Try doing a printf() on C with a non-zero ended string, and it will print whatever is in memory until it finds a zero). This of course is pretty dangerous, and one has to use functions like strncpy (notice the "n") indicating that you should manually input the number of chars from the offset until it ends.

A way to circumvent this is storing the used space in the start of the memory address, something like

struct
{
    int size;
    char *string;
}string;

That stores the size to prevent any issues. Objective-C and many other more abstract language implement in their own way how to handle memory. An NSString* is quite an abstract class to know what happens behind the scenes, it probably inherits all its memory managing from the NSObject.

The whole point I'm try to get is that a pointer contains the starting address, and you can jump from byte-to-byte from there (or jumps of a certain size), keeping in mind the total length of whatever you're storing to avoid doing nasty things like overflowing the stack memory (hence, the name of this site).

Now, how the computer gives this addresses is entirely up to the Operating System, and your logical memory address you use in all your programs is quite different from what the underlying implementation uses (physical memory address). Typically, you'll find that memory is stored in segmented units called "frames", and a used frame is called a "page". And the mapping in between physical and logical is done with a "[Page Table]"2.

As you can see, the software handles pretty much everything, but doesn't mean that there isn't hardware to support this, like the TLB, a cpu-level cache that holds recent memory addresses for quick access.

Also, please take my answer with a grain of salt, it's been a while since I studied these subjects.

OK, my question; I wondered what really happens when you release the
pointer [sPointer release]; are you actually releasing the pointer
(containing the address), or are you also releasing the actual "string
variable" from memory as well? I have learned that when you delete the
reference, the memory where the actual variable is stored will just be
overwritten at the time the compiler needs memory so it does not need
to be cleared at that time. Is this wrong? If it is correct, why do
they say that it's really important to release the NSString pointer
for performance reasons, if you just release the pointer which will
basically contain only a few bytes? Or am I wrong, and is the memory
where the actual variable is stored in fact also cleared at once with
the "release" message?

When you release, you're just decreasing the memory count of the object. What you mean is what happens when it's dealloced (when the count reaches zero).

When you dealloc something, you're basically saying that the space where it has been reserved it's now free to be replaced by anything else requesting memory (through alloc). The variable may still point to a freed space, and this causes problems (Read about dangling pointers and leaks).

The memory might be cleared, but there's no guarantees.

I hope this clears all the doubts, as all of them spawn from your confusion about memory freeing.

And finally also: primitive datatypes are not released, but they "do"
take memory space at the moment of declaration (but not more than a
common pointer). Why shouldn't we release them in fact? What prevents
us from doing something like: int i = 5, followed by [i release]?;

The thing is C has two main things going (actually, a lot more): The Heap that stores memory that has been requested with alloc (or malloc in C), and these require to be freed. And the Stack, which holds local variables, that die when the function/block ends (the stack pops the function call).

In your example, the variable i has been locally declared within its scope, and it's contined in the stack. Trying to peform a dealloc/free (also, the variable i won't respond to release, nor dealloc, as it's not an object) won't work, as is not the type of memory which requires to be freed.

I suggest you going back to C before trying to tackle what Objective-C does, because it's hard to have a clear idea how the imperative programming works with all the nice abstractions like release and dealloc.

披肩女神 2024-12-10 17:02:29

为了论坛的方便,我将对大家的回答做一个简短的总结作为结论。感谢大家的详细说明,迷雾消失了!如果您想要添加或纠正某些内容,请毫不犹豫地做出反应:

  • 纠正:Mac 上的指针占用 4 个字节的内存空间,而不是 2。

  • 指针 *sPointer 指向 NSString 类的实例,而不是直接指向保存字符的内存。
    NSString 实例由一组 iVar 组成,其中有一个指针 iVar 指向分配的内存,其中存储组成字符串的 char 变量(在使用 initWithString: 实例方法时定义)。

  • [sPointer 释放];释放消息不会发送到指针本身,而是发送到 NSString 对象的实例。您不是对指针本身进行操作,而是对指针所指向的内容进行操作(!)。

  • 当发送alloc消息时,NSString实例对象的保留计数增加1。当发送“release”消息时,并不意味着相关内存实际上被清空,而是减少了保留计数1. 当保留计数达到零时,编译器知道之前分配的内存可以再次使用。

  • 内存地址的呈现方式由操作系统决定。程序中使用的逻辑内存地址与底层实现实际使用的(物理内存地址)不同。

  • 本地变量(不一定是原始变量)存储在堆栈内存中(与存储在堆内存中的对象实例不同)。这意味着它们将在函数结束时自动销毁(它们会自动从堆栈中删除)。有关内存构造堆栈和堆的更多信息可以在多个线程中找到,这些线程以自己的方式阐明了用法和差异。例如。 堆栈和堆是什么以及在哪里? / http://ee.hawaii.edu/~tep/EE160/Book/chap14/subsection2.1.1.8.html

For the sake of the forum, I will make a brief and simplified summary of your answers as a conclusion. Thanks to all of you for this extended clarification, the mist disappeared! Don't hesitate to react in case you want to add or rectify something:

  • Rectification: a pointer on the Mac takes 4 bytes of memory space and not 2.

  • The pointer *sPointer points to an instance of the NSString class and NOT directly to the memory where the chars are saved.
    The NSString instance consists of a set of iVars in which there is a pointer iVar that points to memory allocated where the char variables that make up the string are stored (defined when using the initWithString: instance method).

  • [sPointer release]; The release message is not sent to the pointer itself, but to the instance of the NSString Object. You are not acting on the pointer itself, but on what the pointer is pointing to (!).

  • When sending the alloc message, the retain count of the NSString instance object is increased by 1. When sending a "release" message it doesn't mean that the concerned memory is literally being emptied, but it decreases the retain count by 1. When the retain count reaches zero, the compiler knows that the previously allocated memory is available again for re-use.

  • The way memories addresses are presented is decided by the operating system. The logical memory address used in programs is different from what the underlying implementation actually uses (physical memory address).

  • LOCAL variables (not necessarily primitive variables) are stored in the Stack memory (unlike objects instances who are stored in the Heap memory). What this means is that they will be destroyed automatically at the end of a function (they are automatically removed from the stack). More info on the memory constructs stack and heap can be found in several threads that clarify the use and difference in their own way. e.g.. What and where are the stack and heap? / http://ee.hawaii.edu/~tep/EE160/Book/chap14/subsection2.1.1.8.html

何止钟意 2024-12-10 17:02:29

在我回答这些问题之前,你先从一个错误的前提开始。在非 16 位系统上,指针占用超过 2 个字节。在 Mac 上,32 位可执行文件占用 4 个字节,64 位可执行文件占用 8 个字节。

请注意,以下内容并不完全准确(出于优化和其他一些原因,字符串的内部表示有多种, initXXX 函数决定实例化哪种), > 但为了字符串的使用和理解,解释已经足够了。

  1. NSString 是一个类(也是一个相当复杂的类)。字符串(即该类的实例)包含一些管理 ivars 和另一个指针,该指针指向一块分配的内存,该内存足够大,至少可以容纳组成字符串的字节/代码点。您的代码(准确地说,是 alloc 方法)保留足够的内存来包含对象的所有 ivar(包括指向缓冲区的指针)并返回指向该内存的指针。这就是您存储在指针中的内容(如果 initWithString: 没有更改它 - 但我不会在这里讨论它,让我们假设它没有更改)。如果有必要,initWithString:分配足够大的缓冲区来容纳字符串的文本,并将其内存存储在 NSString 实例内部的指针中。所以它是这样的:

     sPointer NSString 实例缓冲区
    +----------------------------------------+ +--------------------+ +- -----+
    | NSString 实例的地址 | ----> |伊瓦尔 | +-> |字符 |
    +-------------------------+ |伊瓦尔 | | |字符 |
                                        | ivar(指针)| --+ |字符 |
                                        |伊瓦尔 | |字符 |
                                        |等等... | |字符 |
                                        +-----------------+ |字符 |
                                                                  |等等|
                                                                  +------+
    
  2. 对于像 @"Hello" 这样的硬编码文字字符串,内部指针仅指向已经存储在程序中的该字符串,在只读存储器中。无需为其分配内存,也无法释放内存。

但我们假设您有一个包含已分配内容的字符串。 release(手动编码或由自动释放池调用)将减少字符串对象的引用计数(所谓的retainCount)。如果该计数达到零,NSString 类的实例将被释放,并且在字符串的 dealloc 方法中,保存字符串文本的缓冲区将被释放。该内存不会以任何方式清除,它只是被内存管理器标记为空闲,这意味着它可以再次重新用于其他目的。

Before I answer the points, you start with a false premise. A pointer takes up more than 2 bytes on a non-16 bit system. On the Mac, it takes up 4 bytes for a 32 bit executable, and 8 bytes in a 64 executable.

Let me note that the following is not entirely accurate (for optimization and some other reasons, there are several kinds of internal representations of strings and the initXXX functions decide which is instantiated), but for the sake of use and understandingof strings, the explanation is good enough.

  1. An NSString is a class (and a rather complicated one as well). A string, i.e. an instance of that class, contains some administrative ivars and one that is another pointer which points to a piece of allocated memory big enough to at least hold the bytes/code points that make up the string. Your code (the alloc method, to be precise) reserves enough memory to contain all the ivars of the object (including the pointer to the buffer) and returns a pointer to that memory. That is what you store in your pointer (if initWithString: doesn't change it -- but I won't go into that here, let's assume it doesn't). If necessary, initWithString: allocates the buffer large enough to hold the text of the string and stores its memory in the pointer for it, inside the NSString instance. So it is like this:

     sPointer                            NSString instance        buffer
    +---------------------------+       +-----------------+       +------+
    | addr of NSString instance | ----> | ivar            |   +-> | char |
    +---------------------------+       | ivar            |   |   | char |
                                        | ivar (pointer)  | --+   | char |
                                        | ivar            |       | char |
                                        | etc...          |       | char |
                                        +-----------------+       | char |
                                                                  | etc. |
                                                                  +------+
    
  2. In the case of a hard-coded, literal string like @"Hello", the internal pointer only points to that string, which is already stored in the program, in readonly memory. No memory has to be allocated for it, and the memory can't be freed either.

But let's assume you have a string with allocated contents. release (either coded manually, or invoked by an autorelease pool) will decrement the reference count of the string object (the so called retainCount). If that count reaches zero, your instance of the NSString class will be dealloced, and in the dealloc method of the string, the buffer holding the string text will be released. That memory is not cleared in any way, it is only marked as free by a memory manager, which means it can be re-used again for some other purpose.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文