gpt4 book ai didi

objective-c - 返回数组中* Fraction对象之和的函数不起作用

转载 作者:太空宇宙 更新时间:2023-11-04 05:42:03 24 4
gpt4 key购买 nike

对于下面的代码。。。
1)当我在主程序中调用*sumFrac时,[result release]是否在函数中被释放?
2)当我试图用[fractionArray release]释放分数数组对象时,为什么会收到编译器错误?
3)最后,函数实际上不返回和,而是返回0/0。为什么会这样?
很抱歉,如果这是显而易见的,那对我来说是新的。。。谢谢你

#import <Foundation/Foundation.h>
#import <Fraction.h>

Fraction * arraySum (Fraction *fracArray[], int arrayLength)
{
Fraction *sumFrac = [[Fraction alloc] init];
Fraction **fractsPtr;

for ( fractsPtr = fracArray; fractsPtr < arrayLength; ++fractsPtr )
sumFrac = [*fractsPtr add: *(fractsPtr + 1)];

return sumFrac;
}

//Test function
int main (int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Fraction *result;

Fraction *a = [[Fraction alloc] initWith: 3 over: 5];
Fraction *b = [[Fraction alloc] initWith: 2 over: 7];
Fraction *c = [[Fraction alloc] initWith: 6 over: 3];

Fraction *fractionArray[] = { a, b, c };

result = arraySum ( fractionArray, 2 );

[result print];

[result release];
[a release];
[b release];
[c release];
[fractionArray release];

[pool drain];
return 0;
}

最佳答案

1)当我在主程序中调用[result release]时,位于函数中的*sumFrac是否被释放?
这是个有点诡计的问题。
sumFrac本身只是指向对象的指针。当你复制一个指针时,不管是通过直接赋值,还是通过=,作为参数传递,从函数返回等等-这只是复制一个指针。因此,result是指向与sumFrac相同对象的指针。所以,当你发送一个release时,它就像发送一个发布到sumFrac一样。
(如果您使用的是ARC,这实际上会变得更加复杂,因为仅仅复制指针有时会自动执行refcount操作。但只要使用正确的名称或属性,它也会成为编译器的问题,而不是您的问题。)
但是,您会重复为sumFrac指定一个新值。每次执行此操作时,它都停止指向旧值。旧值不releases,新值不retains。因此,您返回的值sumFrac确实会被释放,但是,除非arrayLength是0,否则这与您在第一行中分配的值不同。我甚至不知道为什么要分配一个Fraction对象,而只是为了另一个而忽略它,但是如果你想让它工作,你可以:

for ( fractsPtr = fracArray; fractsPtr < arrayLength; ++fractsPtr )
[sumFrac release];
sumFrac = [[*fractsPtr add: *(fractsPtr + 1)] retain];

现在,每次重新分配 sumFrac时,首先释放旧对象并保留新对象,因此每个 Fraction都以相同数量的ref结束(包括具有0个ref的无用新对象),但返回的对象有一个额外的ref,稍后在主函数中 release。(这里我假设 -[add:]返回一个新的、自动释放的 Fraction。如果它改为就地修改对象,或者返回一个新的+1 Fraction,或者其他内容,那就另当别论了。)
如果您很难保持refcounts是直的,那么您可能需要考虑遵循标准的命名约定和/或使用autorelease池和/或ARC。(值得注意的是,您已经有了一个autorelease池)或者,也可以使用Leaks和Xcode附带的其他工具来监视事情,或者使用外接程序代码来转储refcounts,以便以后可以看到它们。
2)当我试图用[firthray release]释放分数数组对象时,为什么会收到编译器错误?
因为 fractionArray是一个 Fraction*[]-也就是一个C风格的 Fraction对象数组,而不是一个 Fraction对象。不能将消息发送到C样式数组,只能发送到对象。
实际上,您在这里得到的错误或警告(取决于编译器设置)已经解释了这一点:
frac.m:61:6: warning: receiver type 'Fraction **' is not 'id' or interface pointer,
consider casting it to 'id'
[fractionArray release];

为了理解这一点,您必须知道 id是一种表示“指向任何ObjC对象的指针”的类型,并且指向对象指针的指针与指向对象的指针不是一回事,所以这可能还不够。但是如果你发布了错误信息而不是仅仅说“我有编译器错误”,你会得到一个即时的答案。
如果要这样做,必须将 release发送到数组中的每个 Fraction对象。你已经在用 [a release]等做了。你根本不需要对数组做任何事情,因为它是在堆栈上分配的(如果你已经用 malloc分配了它,你会想 free它,而不是 release它。)所以,你已经完成了。
但更好的方法是创建一个ObjC数组,它是一个对象:
NSArray *fractionArray = [NSArray arrayWithObjects: a, b, c, nil];
// ...
[fractionArray release];

(除此之外,您实际上不想 release它,因为 arrayWithObjects:返回一个自动释放的数组,并且您有一个自动释放池,所以不要妨碍池的运行。)
3)最后,函数实际上不返回和,而是返回0/0。为什么会这样?
让我们看看你的循环:
for ( fractsPtr = fracArray; fractsPtr < arrayLength; ++fractsPtr )

如果你要做C风格的事情,你会遇到C错误而不是ObjC错误…你在比较 fractsPtr < arrayLength。这将把两者转换成可比较的类型,然后进行比较。 fractsPtr是指向堆栈上数组的指针,因此它显然不小于2。您需要执行以下操作之一:
for ( fractsPtr = fracArray; fractsPtr < fracArray+arrayLength; ++fractsPtr )

……或者
for (i = 0; i < arrayLength; ++i) {
fractsPtr = fracArray[i];

如果没有警告的话,我会非常惊讶。我自己试试,我明白了:
frac.m:34:44: warning: ordered comparison between pointer and integer
('Fraction **' and 'int')
for ( fractsPtr = fracArray; fractsPtr < arrayLength; ++fractsPtr )

警告是有原因的。如果我看到这个,我会立刻找到答案,而不是浪费时间去猜测 add:可能在做什么,等等。即使警告没有向你解释问题,至少在你的问题中提到它。
如果你修好了,会发生什么?好吧,每次通过循环,它都将 sumFracs赋值给 [*fractsPtr add: *(fractsPtr+1)];只有最后一个赋值才重要。所以,它仍然不会求所有分数的和,只是最后两个,换句话说,它将和 [fracArray[arrayLength-1] add:fracArray[arrayLength]]一样。
另外,如果使用一个名为 arrayLength的参数,而它实际上意味着小于数组长度1,则是一种灾难邀请。您知道调用 arraySum(fractionArray, 2)是因为您刚刚编写了代码,但是当您在几周后返回到它时,您将编写 arraySum(fractionArray, 3)(或 arraySum(fractionArray, sizeof(fractionArray)/sizeof(*fractionArray))),它看起来非常正确,以至于您不知道为什么要读取垃圾值或分段。

关于objective-c - 返回数组中* Fraction对象之和的函数不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15693592/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com