0

“sigma 表示法是求和的简写。它在这里的使用意味着将 1/2^i 的值相加,其中 i 从 1 变化到 n。也就是说,添加 1/2 + 1/4 + 1/8 .. .. 如果你使 n 的值足够大,这个系列的总和应该接近 1。让我们尝试不同的 n 值,看看我们有多接近。

#import <Foundation/Foundation.h>
// Define the Fraction class
@interface Fraction : NSObject
{
int numerator;
int denominator;
}
@property int numerator, denominator;
-(void) print;
-(void) setTo: (int) n over: (int) d;
-(Fraction*) add: (Fraction *) f;
-(void) reduce;
@end    

#import "Fraction.h"
@implementation Fraction
@synthesize numerator, denominator;
-(void) print
{
NSLog (@"%i/%i", numerator, denominator);
}
-(void) setTo: (int) n over: (int) d
{
numerator = n;
denominator = d;
}
-(Fraction *) add: (Fraction *) f
{
// To add two fractions:
// a/b + c/d = ((a*d) + (b*c)) / (b * d)
// result will store the result of the addition
Fraction *result = [[Fraction alloc] init];
result.numerator = numerator * f.denominator +
denominator * f.numerator;
result.denominator = denominator * f.denominator;
[result reduce];
return result; 
}

#import "Fraction.h"
int main (int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
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 your value for n:");
scanf ("%i", &n);
pow2 = 2;

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

NSLog (@"After %i iterations, the sum is %g", n, [sum convertToNum]);
[aFraction release];
[sum release];
[pool drain];
return 0;
}

问题:为什么我们必须创建在“for”循环中使用的附加变量 sum2?为什么我们需要在这里“释放先前的总和”,然后再给它一个我们刚刚释放的值?:

sum2 = [sum add: aFraction];
[sum release]; // release previous sum
sum = sum2;

难道只是为了避免内存泄漏?(方法“add”初始化一个存储在 sum2 中的变量)

4

2 回答 2

2

没有看到如何Fraction定义,我不能确定,但​​我猜一个Fraction对象是不可变的,所以sum不能简单地改变。如果我们这样做了sum = [sum add:aFraction],它会泄漏sum曾经指向的对象(它有一个正的保留计数,仍然如此,而且我们不再有指向它的指针)。

于 2012-09-25T21:44:11.663 回答
1

在不知道Fraction最有可能成为本书一部分的类的情况下,它可能只是不可变对象使用的一个示例。

通常提倡不可变对象,因为:

  • 使它们线程安全很容易;和
  • 因为他们保证不会改变每个人都可以可靠地坚持同一个而不是复制令人作呕的价值。

因此,您可以随心所欲地进行多处理,并且在任何相当复杂的系统中,您通常会在保持面向对象的同时节省内存(即,每个对象都是独立的,没有其他人直接操作对象的内部数据)。

作为不可变的,当你想“修改”一个现有的时,你必须创建一个新的,我认为这就是这里发生的事情。

编辑:使用完整的源代码,Fraction它看起来对象实际上是可变的(例如,它有setTo:over:)。所以答案仍然是旧对象被丢弃而新对象被保留,因为add:它不会改变它被调用的对象,而是返回一个带有最终结果的新对象。尽管从风格上看,它似乎更像是对三地址形式的追求,而不是不可变对象模式。

于 2012-09-25T21:44:27.747 回答