这是Objective-C指针的有效使用吗?

时间:2009-03-20 21:18:31

标签: iphone objective-c cocoa cocoa-touch

这是一个初学者级别的问题,我很好奇这是否是在语句中有效使用指针,如:

 NSMutableDictionary *foo = [bar mutableCopy];

当有效时与我需要执行以下操作时,我感到困惑:

NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0];
foo = [bar mutableCopy];
// use foo
[foo release];

两者都有效吗?何时使用其中一个?

5 个答案:

答案 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。