函数返回分数对象*总和不工作

对于下面的代码数组...
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)当我在主程序中调用[结果释放]时,位于函数中的* sumFrac被释放了吗?

这是一个技巧性的问题。

sumFrac本身只是一个指向对象的指针。当你复制一个指针时 - 无论是通过直接赋值=,作为参数传递,从函数返回等 - 这只是复制一个指针。因此,result是与sumFrac相同的对象的指针。所以,当你发送一个release时,就像发送一个发布到sumFrac。 (如果你使用的是ARC,这实际上会变得更加复杂,因为只是复制一个指针有时会自动进行refcount的操作,但它也会成为编译器的问题,而不是你的问题,只要你使用正确的名字或属性。)

但是,您重复为sumFrac分配新值。每次你这样做,它都会停止指向旧值。没有什么release是旧值,或retain是新值。因此,您返回的值为sumFrac确实获得释放 - 但是,除非arrayLength为0,这与您在第一行中分配的值不同。我什至不知道为什么你分配一个Fraction对象时,你只是忽略它支持一个不同的,但如果你想使这项工作,您可以:

for (fractsPtr = fracArray; fractsPtr < arrayLength; ++fractsPtr) 

[sumFrac release];

sumFrac = [[*fractsPtr add: *(fractsPtr + 1)] retain];

现在,每次你重新分配sumFrac时,你首先释放旧的对象并保留新的对象,因此每个Fraction最后都以相同数量的引用开始(包括无用的新引用),除了你返回的引用有一个额外的参考,你后来release在主要功能。 (我在这里假设-[add:]返回一个新的自动发布的Fraction。如果它改变了对象的位置,或者返回一个新的+1 Fraction或其他的东西,那么这是一个不同的故事。)

如果您很难保持refcounts直接,您可能需要考虑遵循标准的命名约定和/或使用autorelease池和/或ARC。 (值得注意的是,你已经有一个自动释放池。)或者,也可以使用Leaks和Xcode附带的其他工具来观察事物,或者添加代码来删除refcounts,以便稍后可以看到它们。

2)为什么我试图用[分数阵列版本]释放分数阵列对象时收到编译器错误?

由于fractionArrayFraction*[],也就是说,Fraction对象,而不是一个对象Fraction的C数组。您不能将消息发送到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:返回一个autoreleased数组,和你有一个自动释放池,所以在池的方式没有得到。)

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))),它看起来很明显,你会有不知道为什么你阅读垃圾值或segfaulting。

回答:

该代码是非常奇怪的。

根本没有数组对象;你有一些相当奇怪的托管语言数组。

我建议重构代码以使用NSMutableArray来包含分数,因为几乎不会看到像在真实的ObjC应用程序中编写的代码。

以上是 函数返回分数对象*总和不工作 的全部内容, 来源链接: utcz.com/qa/257839.html

回到顶部