Objective-C 内存管理
我对 Objective-C 的内存管理有一些疑问,
比方说:
NSString * test= [[NSString alloc] init ]
test=@"msg";
[object setStr1: test ]; // declared as: @property(copy, readwrite)
[object setStr2: test ]; // declared as: @property(retain, readwrite)
[object setStr3: test ]; // declared as: @property(assign, readwrite)
test=@"some other string"
我认为 str1
将拥有 test
内容的副本:str1
将指向到包含msg
的内存(堆)的一个地址,该地址与test
指向的地址不同。正确的?
关于str2:
1.它存储了什么?,我猜是指向test
的相同地址,但它会将test
的引用计数器增加到2。
2.当我改变测试内容时,str2有什么?我猜它仍然指向
关于str3的msg
:这是不正确的,对吧?assign
是做什么的?
谢谢。
额外问题:
NSString * test= [[NSString alloc] init ]
test=@"msg";
test=@"something";
我应该在更改内容之前发布测试吗?
i have some questions about objective-c's memory management,
let's say:
NSString * test= [[NSString alloc] init ]
test=@"msg";
[object setStr1: test ]; // declared as: @property(copy, readwrite)
[object setStr2: test ]; // declared as: @property(retain, readwrite)
[object setStr3: test ]; // declared as: @property(assign, readwrite)
test=@"some other string"
I think str1
will have a copy of test
s content: str1
will point to one adress of the memory (heap) that contais msg
, this address is not the same pointed by test
. right?
about str2:
1. what does it store?, i guess the same address that points test
, but it will increase the reference counter of test
to 2.
2. when i change the test's content, what does str2 have? I guess it still points to msg
about str3: it's incorrect, right?, what does assign
do?
thanks.
bonus question:
NSString * test= [[NSString alloc] init ]
test=@"msg";
test=@"something";
should i release test before changing its content?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里要讲的最重要的事情:赋值运算符
=
永远不会改变(即更改)对象。改变对象只能通过向其发送消息来完成(例如,将appendString:
发送到NSMutableString
)。赋值运算符只是使指针指向与以前不同的对象。因此,以下说法是不正确的:
第 (1) 行创建一个 NSString 对象,并分配
test
指向它。第 (2) 行做了同样的事情:它创建一个新的、不相关的 NSString 对象,并分配test
指向它。现在,第 (1) 行创建的原始 NSString 没有任何内容指向它,并且被泄漏。此外,您永远不需要
分配
字符串文字;当您使用@"..."
语法时,编译器会隐式执行此操作。一般来说,你很少需要使用[NSString alloc]
(仅当你想使用各种init*
方法时,例如initWithFormat:
等)str1
将指向测试字符串的不同副本。 (勘误表:根据 Eiko 的说法,如果它是不可变的,接收器将简单地将其视为“保留”。如果您行为正确,这不会产生实际差异。)str2
将指向与test,并且该对象的保留计数将会增加。str3
将指向与 test 相同的位置,但保留计数不会增加。一般来说,字符串是不可变的,因此您无法更改其内容。然而,您可能需要注意 NSMutableString 的实例,它是 NSString 的子类。这就是为什么许多人建议复制字符串而不是保留它们,这样,如果程序的其他部分改变了字符串,对象的副本将不受影响。
The most important thing to take away here: The assignment operator
=
never mutates (i.e. changes) an object. Mutating an object can only be accomplished by sending it messages (e.g., sendingappendString:
to anNSMutableString
). The assignment operator simply causes a pointer to point to a different object than it did before.Thus, it is incorrect to say:
Line (1) creates an NSString object, and assigns
test
to point to it. Line (2) does the same thing: it creates a new, unrelated NSString object, and assignstest
to point to it. Now the original NSString created by line (1) has nothing pointing to it, and is leaked.Also, you never need to
alloc
a string literal; the compiler does this implicitely when you use the@"..."
syntax. In general, you will very rarely have to use[NSString alloc]
at all (only when you want to use the variousinit*
methods, such asinitWithFormat:
, etc.)str1
will point to a distinct copy of the test string. (Errata: According to Eiko, the receiver will simply treat this as a 'retain' if it is immutable. This makes no practical difference if you are behaving correctly.)str2
will point to the same location as test, and the retain count of the object there will be incremented.str3
will point to the same location as test, but the retain count will not be incremented.Generally speaking, strings are immutable, so you cannot change their content. You may have to watch out for instances of NSMutableString, however, which is a subclass of NSString. This is why many people recommend copying strings instead of retaining them, so that, should the string be mutated by another part of the program, your object's copy will be unaffected.
在第二行中,您已经泄漏了内存,因为您将测试重新分配给了一个新对象,并丢失了对在第一行中创建的对象的引用。
你对 str1 的结论是错误的,因为副本可能只是返回 self 对于不可变类型(它们无论如何都不会改变,所以通常系统足够聪明,可以只保留它们一次)。
str2 确实会指向同一个对象,只是增加保留计数。您无法更改测试的内容,因为它是不可变的。如果它是 NSMutableString,那么是的,str2 也会显示此更改。
为 str3 分配只会“复制地址”,因此它指向同一个对象(与 str2),但它不会保留它,因此它不会声明该对象的任何所有权/权益。如果你在其他地方释放它,str3将指向死内存。
额外奖励:正如我的介绍所示,是的,你泄漏了。分配@“msg”会使您泄漏原始对象,因为@“msg”将创建一个新对象。
With your second line you already leak memory, because you reassign test to a new object and lose the reference to the object you created in your first line.
Your conclusion to str1 is wrong, because the copy might just return self for immutable types (they don't change anyway, so often the system is smart enough to keep them around just once).
str2 will indeed point to the same object and just increment the retain count. You cannot change test's content, as it is immutable. If it was an NSMutableString, then yes, str2 would show this change, too.
assign for str3 will just "copy the address", so it points to the same object (as str2), but it does not retain it, so it doesn't claim any ownership/interest in that object. If you release it elsewhere, str3 will point to dead memory.
Bonus: As in my introduction, yes, you leak. Assigning @"msg" makes you leak the original object, as @"msg" will create a new one.