0

我对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会有一个tests 内容的副本:str1将指向包含 的内存(堆)的一个地址msg,该地址与 所指向的地址不同test。对?

关于str2:
1.它存储什么?,我猜指向的地址相同test,但它会将引用计数器test增加到2。2
.当我更改测试的内容时,str2有什么?我想它仍然指向msg

关于str3:这是不正确的,对吧?,有什么作用assign

谢谢。

奖金问题:

NSString * test= [[NSString alloc] init ]
test=@"msg";
test=@"something";

我应该在更改其内容之前发布测试吗?

4

2 回答 2

3

这里最重要的一点是:赋值运算符=永远不会改变(即改变)一个对象。改变一个对象只能通过向它发送消息(例如,发送appendString:到一个NSMutableString)来完成。赋值运算符只是使指针指向与以前不同的对象。

因此,这样说是不正确的:

(1) NSString * test = [[NSString alloc] init];
(2) test = @"msg";

第 (1) 行创建了一个 NSString 对象,并赋值test为指向它。第 (2) 行做了同样的事情:它创建了一个新的、不相关的 NSString 对象,并分配test给它指向它。现在由第 (1) 行创建的原始 NSString 没有任何指向它,并且被泄露了。

此外,您永远不需要alloc字符串文字;当您使用@"..."语法时,编译器会隐式执行此操作。一般来说,您很少需要使用[NSString alloc](仅当您想使用各种init*方法时,例如initWithFormat:等)

  1. str1将指向测试字符串的不同副本。(勘误表:根据 Eiko 的说法,如果它是不可变的,接收器将简单地将其视为“保留”。如果您的行为正确,这没有实际区别。)
  2. str2将指向与 test 相同的位置,并且该对象的保留计数将增加。
  3. str3将指向与测试相同的位置,但保留计数不会增加。

一般来说,字符串是不可变的,所以你不能改变它们的内容。但是,您可能需要注意 NSMutableString 的实例,它是 NSString 的子类。这就是为什么许多人建议复制字符串而不是保留它们的原因,这样,如果字符串被程序的另一部分更改,对象的副本将不受影响。

于 2010-09-09T18:31:59.887 回答
1

在您的第二行中,您已经泄漏了内存,因为您将 test 重新分配给一个新对象并丢失了对您在第一行中创建的对象的引用。

您对 str1 的结论是错误的,因为对于不可变类型,副本可能只返回 self (它们无论如何都不会改变,因此系统通常足够聪明,可以只保留它们一次)。

str2 确实会指向同一个对象,并且只会增加保留计数。您不能更改测试的内容,因为它是不可变的。如果它是 NSMutableString,那么是的,str2 也会显示这种变化。

为 str3 赋值只会“复制地址”,因此它指向同一个对象(与 str2 相同),但它不保留它,因此它不要求对该对象的任何所有权/权益。如果你在别处释放它,str3 将指向死内存。

奖励:正如我的介绍,是的,你泄漏了。分配@"msg" 会使您泄漏原始对象,因为@"msg" 将创建一个新对象。

于 2010-09-09T18:35:52.293 回答