【问题标题】:Is it OK to reuse variables in Objective-C?在 Objective-C 中重用变量可以吗?
【发布时间】:2015-01-09 18:16:59
【问题描述】:

请注意Category 变量在以下两种方法中的使用方式。我认为方法 1 不好,因为每个循环都会创建一个变量的新实例,那么为什么我会看到这么多使用这种策略的代码示例呢?我认为方法 2 会更好,因为它会使用更少的内存。

方法一

NSData * data = [NSData dataWithContentsOfURL:url];  
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

for (int i=0; i < json.count; i++)
{
    NSString * Category = [[json objectAtIndex:i] objectForKey:@"CategoryID"]; 

    //do something here
}

 方法 2

NSURL * url = [NSURL URLWithString:getDataURL];
NSData * data = [NSData dataWithContentsOfURL:url];  
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

NSString * Category 
for (int i=0; i < json.count; i++)
{
    Category = [[json objectAtIndex:i] objectForKey:@"CategoryID"];

    //do something here
}

【问题讨论】:

  • 保持你的代码尽可能清晰,让编译器担心优化,除非分析显示你有问题。
  • 忽略 ARC,它们都使用相同数量的内存。 “创建”一个局部变量不需要任何成本。一般来说,变量的范围应该尽可能小(更容易理解和更少的错误),这对于 ARC 来说是双倍的。

标签: objective-c variables memory


【解决方案1】:

这两种方法在功能上是相同的。您在第二个中所做的只是为变量提供更广泛的范围(在第一个版本中,范围仅限于循环)。

因此,您应该更喜欢第一个版本,因为应尽可能限制范围。

每次仍会创建一个新值。您将变量声明与变量赋值混淆了。

【讨论】:

    【解决方案2】:

    您的第一个示例是更好的方法。创建变量声明没有成本。如果不需要,编译器会将其优化掉。重用变量是常见的错误来源,通常应避免。

    重用对象是完全不同的事情,有时对性能非常重要。但是Category 不是一个对象,它只是一个指向对象的指针。 (请注意,变量应始终具有前导小写。前导大写表示它是一个类。)

    即便如此,这仍然不是最好的方法。您应该尽可能避免使用objectAtIndex:,而是使用枚举。这更安全、更清晰、更有效。

    NSData * data = [NSData dataWithContentsOfURL:url];  
    NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
    // You really should validate that json is an array and check for errors. 
    
    for (NSString *category in [json valueForKey:@"CategoryID"])
    {
        //do something here
    }
    

    这通过使用 KVC 方法 [NSArray valueForKey:] 来工作,该方法返回给定属性的新数组。也就是说,如果您从外部来源提取,则需要非常小心。如果你得到格式错误的数据,你就会崩溃。您需要确保获得预期的结果。

    【讨论】:

      【解决方案3】:

      局部变量是在堆栈上创建的。当您进入作用域时,堆栈指针会移动以为变量腾出空间。然后,当您离开作用域时,该变量的空间会从堆栈顶部弹出。

      当您谈论作为对象指针的变量时,我们谈论的是 4 或 8 个字节(32 位设备为 4 个字节,64 位设备为 8 个字节。)内存量很小。

      在您的第一个示例中,堆栈指针被移动以在 for 循环的开头为 Category 变量(应该是小写,category 以遵循 Cocoa 命名约定顺便说一句)腾出空间,然后一旦循环完成执行,内存就会被丢弃。内存从不浪费,只是暂时使用。

      说“...每个循环都会创建一个变量的新实例”是不正确的。该变量在进入循环之前创建并丢弃后记。

      在您的第二个示例中,变量是在方法的范围内定义的。因此,4(或 8)个字节一直存在,直到方法完成。但是,一旦该方法完成,无论如何都会恢复内存。

      除非您有堆栈溢出,否则局部变量不是有意义的内存消耗者。 iOS 设备有数百兆的内存,也许是千兆字节。那是数亿字节,甚至数十亿字节。担心单指针局部变量就像比尔盖茨担心零钱一样。我曾经读到有人计算过,盖茨在担任微软 CEO 的时候,如果他在街上看到一张 100 美元的钞票,花几秒钟弯腰去捡它是不划算的利用时间。他会多花几秒钟做他的工作来赚更多的钱。担心指针变量的空间就像盖茨担心少一张一美元的钞票(一张他会在几分之一秒后取回的美元钞票!)

      【讨论】:

      • 感谢您抽出宝贵时间回复。我喜欢盖茨的比喻。
      • 没问题。我保证我没有杀你父亲! (公主新娘参考)
      猜你喜欢
      • 2010-11-10
      • 1970-01-01
      • 2011-04-06
      • 2012-04-02
      • 2011-02-09
      • 1970-01-01
      • 2012-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多