tags:

views:

117

answers:

2

I'm trying to understand an example in the Kochan Obj-C 2.0 book. It looks like this. Basically we have a standard add fraction method:

-(Fraction *)add:(Fraction *) f {
Fraction *result = [[Fraction alloc] init];
int resultNum, resultDenom;
resultNum = nermator *f.denominator + denominator*f.numerator;
resultDenom = denominator *f.denominator
// numerator and denominator are instance variables 
[result setTo: restultNum over: resultDenom]; // another method that sets the fraction (e.g. 1/4)
[result reduce];
return result}

There are two examples using this that I don't understand, one in a main.m test file they do:

Fraction *aFraction = [[Fraction alloc] init];
Fraction *bFraction = [[Fraction alloc] init];
Fraction *resultFraction;

[aFraction setTo: 1 over: 4];
[bFraction setTo: 1 over: 2];

resultFraction = [aFraction add: bFraction];

I don't understand why you don't need to alloc and init resultFraction before using the add method. (Question #1) Also, by doing this, does resultFraction now have a reference count of 1? Or because it was never alloc'd and init'd, is it's reference count still 0?

Using the same Fraction class and methods, they show an example of how to calculate the summation of 1/2^n

Here is the code:

Fraction *aFraction = [[Fraction alloc] init];
Fraction *sum = [[Fraction alloc] init], *sum2;
int i, n, pow2;

[sum setTo: 0 over:1]; // set 1st fraction to 0

NSLog(@"Enter n:");
scanf("%i", &n);

pow2 = 2;
for (i = 1; i <=n; ++i) {
[aFraction setTo: 1 over: pow2];
sum2 = [sum add: aFraction];
[sum release];
sum = sum2;
pow2 *=2;
}

In this example, sum is alloc'd and init'd, and added to aFraction, and the result is assigned to sum2, then sum is released. So how is it in the next line (sum = sum2), sum holds that value still? Cause doesn't sum now have a reference count of 0 after being released since it was only initialized once. I thought sum2 would have the increased reference count and that would need to be relased after it gets assigned to sum.

Sorry for the noob questions.

+4  A: 

Question #1

The reason you don't need to alloc and init the result fraction is because the add method does that for you. (Line 2) It's reference count is now one because it was never released. ([resultFraction release];)

Question #2

In this example, you are indeed correct that sum should have a reference count of 0 at that point after being released. This should be fine. sum2, however, is still valid and you are assigning that to sum.

This is simple pointer assignment. sum is a pointer and it simply looks at a chunk of memory. When that chunk of memory is released, it will eventually be collected. The assignment of sum = sum2 just copies the location of the object sum2 represents to sum.

For more information on pointers: http://www.informit.com/articles/article.aspx?p=1272497&amp;seqNum=2

Chad Stewart
Incidentally, the Fraction that you get from `add:` *should* have been autoreleased in the `add:` method. It isn't in this case, but that is clearly a mistake.
Chuck
In Regards to Question #2, is this also why [sum2 release] is not called? In the first example, resultFraction has to be released at the end, but by assigning sum to sum2, both pointing to the same point in memory, by releasing that object with [sum release], it is essentially the same as [sum2 release]?sum2 = [sum add: aFraction]; // sum2 has retain count 1, sum has retain count 1[sum release]; // sum has retain count 0 sum = sum2; // sum, sum2 have retain count 1Is that right? Thanks again!
jet
That is correct. If you were to do a [sum2 release] you would invalidate sum and sum2 as they are referencing the same memory. When you say: sum = sum2sum and sum2 effectively point at the same exact place in memory, thus they contain the same exact data. If you were to dereference and change sum, sum2 would reflect that.
Chad Stewart
+1  A: 

What is commonly overlooked by Objective-C beginners is that your variable names such as aFraction and bFraction just point to an object, they don't represent the actual object in memory. It is entirely possible for aFraction and bFraction to point to the same object, just by setting one to the other.

At the beginning, the resultFraction variable is declared but not yet set up to point to anything. When you invoke the add: method on your aFraction object, the method returns a newly allocated object (that contains the result of your addition), and the resultFraction variable now points to that new object.

dreamlax