这是一个初学者级别的问题,我很好奇这是否是在语句中有效使用指针,如:
NSMutableDictionary *foo = [bar mutableCopy];
当有效时与我需要执行以下操作时,我感到困惑:
NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0];
foo = [bar mutableCopy];
// use foo
[foo release];
两者都有效吗?何时使用其中一个?
答案 0 :(得分:9)
猜测为什么你可能会感到困惑,我想补充说明第二个代码示例实际上做了什么(以及为什么没有必要)。
NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0];
我认为你对这条线感到困惑,因为这条线通常被描述为“初始化foo”。这有点误导。技术上在这里改变了2个不同的实体 - 创建了新的NSMutableDictionary
对象,并为“foo”变量分配了它的地址。
该行实际上在堆上创建了一个新的NSMutableDictionary
对象(应用程序的动态内存区域)。我称之为“词典1”。这样就可以找到堆上的这个新的“Dictionary 1”对象,它的内存地址存储在“foo”中。 “foo”的角色是充当索引,所以我们可以找到“词典1”。
虽然我们经常说:“foo是一本字典”,那是因为我们很懒 - 这句话在技术上是错误的。正确地说:“堆上有一个字典,foo存储它的内存地址,以便我们可以找到它并使用它。”
然后运行以下行:
foo = [bar mutableCopy];
你正在使用“bar”中的地址在堆中找到一个不同的对象(我将其称为“Dictionary 2”),并在堆上创建另一个具有相同值的对象(“Dictionary 3”) 。如果你保持计数,现在就有3个物体。
在制作“Dictionary 3”之后,将其存储器地址存储在“foo”变量中。存储到“foo”中会覆盖现有的存储器地址(指向“Dictionary 1”的地址)。这意味着我们没有剩余指向“Dictionary 1”的指针,因此永远无法再找到它。这就是我们说“词典1”泄露的原因。
我希望你能从这种情况看出为什么从不需要“词典1”(你只是打算用“foo”来访问副本,“词典3”)。
答案 1 :(得分:7)
您永远不需要在第二个示例中编写代码。除了泄密记忆外,[[NSMutableDictionary alloc] initWithCapacity:0]
什么都不做。
在第二个示例中,您创建了一个NSMutableDictionary并将其分配给foo
。然后在下一行中,将另一个NSMutableDictionary的副本分配给foo
,这意味着指向的原始字典foo
现在只是浮动在堆上的某个地方,无法被释放。
然而,您需要在Objective-C memory management guidelines中列出foo
中列出的{{1}}。
答案 2 :(得分:3)
第一个是正确的,第二个是泄漏内存,因为你分配了两次(复制计为一个)并且只释放一次。
完成后不要忘记释放foo
答案 3 :(得分:1)
赋值行为将覆盖该变量持有的先前值。例如:
x = 3
x = 4
第二行开头的x所持有的值是3,但是在执行代码行之后,它是4.语法:
int x = 0;
实际上只是简写:
int x;
x = 0;
作为指针的变量没有什么不同。因此,如果变量的第一个引用只是分配给它,则不需要先对其进行初始化,因为您初始化它的任何值都将被丢弃。
答案 4 :(得分:0)
第一个是正确的方法。 copy和alloc都会为你的变量分配内存。因此,使用第二个选项会将变量的保留计数增加到2。