内存使用的N个建议

1> 使用alloc、new、copy族(如mutableCopy)创建的对象,要使用release/autorelease。使用retain的对象,同样处理。没有使用这四者的,不能用release/autorelease。

// 必须release
TestClass *ptr = [[TestClass alloc] init];
...
[ptr release];


// 不用release
NSString *str;
str = [NSString stringWithFormat:@"Some string here..."];
NSLog(str);


// 使用getter得到的,不增加引用计数,所以不用release
NSString *str;
str = [TestClass firstName];


2> alloc之后立刻init

TestClass *ptr = [TestClass alloc]; // 这样写是有问题的,因为alloc有可能失败
[ptr init]
if (ptr) {
    ...


正确的写法:TestClass *ptr = [[TestClass alloc] init];

3> 给野指针赋空值:nil

#import "TestClass.h"

@implementation TestClass


-(NSString *) str

{
    return str;
}

-(void) setStr:(NSString *)input

{
    [input retain];
    [str release];
    str = input;
}

-(void) dealloc

{
    [str release];
    [super dealloc];
}

@end


#import "TestClass.h"

 
int main(int argc, const char * argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
    TestClass *ptr = [[TestClass alloc] init];
    [ptr setStr:@"Fubar"];
 
    [ptr release];
    [pool drain];
    return 0;
}


上面的程序看似毫无问题,但还是有问题的。

-(void) dealloc
{
    [str setStr:nil];
    [super dealloc];
}


[str setStr:nil] 来代替 [str release] 更好,可消灭野指针,和C++是一样的道理。
注:当input为nil时,[input retain] 还是合法的调用,不会引起异常。所以调用前无需检查空指针。
另外,[str setStr:nil] 还可以写成 self.str = nil ,一样是调用setter。但不能直接写成 str = nil ,这是内存泄漏。

4> iPhone 3G 有128M的内存。但给你的App的只有大约40M。即使你只用了3M内存,也有可能收到内存警报。
5> 即使用Objective-C 2.0编程,在iPhone上也没有垃圾收集机制。
6> Objective-C runtime 不允许在栈上创建对象,只能在堆上。所以不能使用智能指针帮助管理对象资源。
7> 用autorelease要小心。内存池释放时,它们才释放。如果不小心就和内存泄漏没大区别。释放内存池会花很多时间,如果里面有几万个小对象的话。

// 这样创建的都是autorelease对象,必须由内存池释放。少用!
NSString *string = [NSString stringWithFormat:@"value = %d", intVariable];

// 使用这样的方法,可以更好地利用iPhone的内存

NSString *string = [[NSString alloc] initWithFormat:@"value = %d", intVariable];
...
[string release];

// 或者在循环的时候用autorelease对象

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (id item in array)
{
    id anotherItem = [item createSomeAutoreleasedObject];
    [anotherItem doSomethingWithIt];
}
[pool release];


另外,千万不要对autorelease对象使用release方法:程序极可能会立刻崩溃!

8> iPhone没有内存交换文件,没有虚拟内存。物理内存没有的时候,App就挂掉了。
9> 在内存报警时,即使无法释放无用内存,至少也要像下面这样:
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}


或者在application delegate里写上一点儿:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
    [[ImageCache sharedImageCache] removeAllImagesInMemory];
}


NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
        selector:@selector(whatever:)
        name:UIApplicationDidReceiveMemoryWarningNotification
        object:nil];

- (void) whatever: (NSNotification *)note {...}


10> 申请资源时,用“懒汉策略”

@interface UITableViewControllerSubclass
{
@private
    NSMutableArray *items;
    DetailController *detailController;
    UINavigationController *navigationController;
}
@end

@implementation UITableViewControllerSubclass


- (id)init

{
    if (self = [self initWithStyle:UITableViewStylePlain])
    {
        // only basic stuff
        items = [[NSMutableArray] alloc] initWithCapacity:20];
        navigationController = [[UINavigationController alloc]
                                initWithRootViewController:self];
    }
    return self;
}

- (void)dealloc

{
    [items release];
    [detailController release];
    [navigationController release];
    [super dealloc];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{
    Item *item = [items objectAtIndex:indexPath.row];
    if (detailController == nil)    // 在需要的时候才分配内存
    {
        detailController = [[DetailController alloc] init];
    }
    detailController.item = item;
    [self.navigationController
        pushViewController:detailController
                  animated:YES];
}
...


可以使用 UIViewController 的 viewWillAppear 和 viewDidDisappear 来申请/释放资源。
可以使用 UITabBarControllerDelegate 的 tabBarController:didSelectViewController: 来进一步控制资源的加载和释放。

11> 使用正确的setter:

@interface SomeClass
{
@private
    NSArray *items;
    NSString *name;
    id<someProtocol> delegate;
}

@property (nonatomic, retain) NSArray *items;

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) id<someProtocol> delegate;
@end

@implementation SomeClass


@synthesize items;

@synthesize name;
@synthesize delegate;

- (void)dealloc

{
    [items release];
    [name release];
    delegate = nil;
}

- (void)setItems:(NSArray *)obj

{
    if (obj == items) {
        return;
    }

    [items release];
    items = nil;        // 很重要!参数obj有可能为空
    items = [obj retain];

    if (items != nil) {
        ...
    }
}

- (void)setName:(NSString *)obj

{
    [name release];
    name = nil;
    name = [obj copy];   // NSStrings总要用copy

    if (name != nil) {
        ...
    }
}

- (void)setDelegate:(id<someProtocol>)obj

{
    // 身为delegate,只需assign,不要增加引用计数
    delegate = obj;

    if (delegate != nil) {
        ...
    }
}

@end


12> 正确地处理delegate的dealloc:

@interface SomeClass <WidgetDelegate>
{
@private
    Widget *widget;
}
@end

@implementation SomeClass


- (id)init

{
    if (id = [super init]) {
        widget = [[Widget alloc] init];
        widget.delegate = self;
    }
    return self;
}

- (void)dealloc

{
    widget.delegate = nil;    // delegate已经消亡,而widget未必,所以要置空,免得
    [widget release];           // widget以后调用已经不存在的delegate的方法,会crash的!
    [super dealloc];
}

- (void)widget:(Widget *)obj callsItsDelegate:(BOOL)value

{
    // and here something happens...
}

@end

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个问题要求编写程序,根据输入学生的成绩,统计并输出学生的平均成绩、最高成绩和最低成绩。建议使用动态内存分配来实现。 输入格式: 输入第一行首先给出一个正整数n,表示学生个数。接下来一行,给出n个正整数,分别是每个学生的成绩。 输出格式: 按照以下格式输出统计结果,其中平均成绩精确到小数点后一位,其余结果向下取整。 平均成绩=平均成绩值 最高成绩=最高成绩值 最低成绩=最低成绩值 输入样例: 5 90 87 66 100 77 输出样例: 平均成绩=84.0 最高成绩=100 最低成绩=66 ### 回答2: 本题要求编写程序,根据输入学生的成绩,统计并输出学生的平均成绩、最高成绩和最低成绩,并建议使用动态内存分配来实现。 首先,我们需要读入数据,即学生的个数n和每个学生的成绩。可以使用scanf函数来完成输入,具体代码如下: scanf("%d", &n); // 读入学生个数 int* scores = (int*)malloc(n * sizeof(int)); // 动态内存分配 for (int i = 0; i < n; i++) { scanf("%d", &scores[i]); // 读入每个学生的成绩 } 接下来,我们可以使用一个循环来遍历所有学生成绩,统计最高成绩和最低成绩,并累加所有成绩的和。具体代码如下: int max_score = scores[0]; // 最高成绩初始化为第一个学生的成绩 int min_score = scores[0]; // 最低成绩初始化为第一个学生的成绩 int sum = scores[0]; // 所有成绩的和初始化为第一个学生的成绩 for (int i = 1; i < n; i++) { // 从第2个学生开始遍历 if (scores[i] > max_score) { // 如果该学生的成绩高于当前最高成绩 max_score = scores[i]; // 更新最高成绩 } if (scores[i] < min_score) { // 如果该学生的成绩低于当前最低成绩 min_score = scores[i]; // 更新最低成绩 } sum += scores[i]; // 累加所有成绩的和 } 最后,我们可以根据求得的最高成绩、最低成绩和所有成绩的和,计算出学生的平均成绩,并输出这三个值。具体代码如下: double avg_score = (double)sum / n; // 计算平均成绩 printf("average = %.2lf\n", avg_score); // 输出平均成绩 printf("max = %d\n", max_score); // 输出最高成绩 printf("min = %d\n", min_score); // 输出最低成绩 最后别忘了释放动态分配内存,具体代码如下: free(scores); // 释放动态分配内存 完整代码如下: ### 回答3: 本题的主要思路是使用动态内存分配来保存学生的成绩,再通过计算来得出平均值、最高值和最低值。 首先,输入学生个数n,使用动态内存分配来开辟一个大小为n的int型数组来保存学生的成绩。然后,读入n个学生的成绩并存入刚分配的数组中。 接着,定义变量来保存平均值、最高值和最低值。使用for循环遍历刚才分配的数组,分别累加学生的成绩并比较取出最高值和最低值。最后,计算平均值并输出即可。 代码实现如下: ```c #include <stdio.h> #include <stdlib.h> // 动态内存分配所需头文件 int main() { int n, *scores; // n表示学生个数, scores为保存学生成绩的指针 int sum = 0, max = 0, min = 100; // sum累加学生成绩, max和min分别保存最高分和最低分 float avg; // 读入学生个数n并使用动态内存分配来为成绩数组scores分配空间 scanf("%d", &n); scores = (int*)malloc(n * sizeof(int)); // 读入n个学生的成绩并存储到scores数组中 for (int i = 0; i < n; i++) { scanf("%d", &scores[i]); sum += scores[i]; if (scores[i] > max) max = scores[i]; if (scores[i] < min) min = scores[i]; } avg = 1.0 * sum / n; // 计算平均分数 // 输出统计结果 printf("平均成绩:%.2f\n最高成绩:%d\n最低成绩:%d\n", avg, max, min); free(scores); // 动态分配的内存要释放掉 return 0; } ``` 需要注意的是,在动态内存分配之后,使用完成后也要使用free()函数来释放掉所分配的内存,以免出现内存泄漏的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值