以下程序中对象的引用计数是多少?

时间:2014-07-19 08:07:52

标签: ios objective-c ios5 ios4

1)禁用ARC。

2)我有以下代码:

- (IBAction)btnsecondClicked:(id)sender {

     NSString *myname;
     myname  = retrieveName();
}


NSString * retrieveName()
{
  NSString *tmpStr = [[NSString alloc] initWithString "StackOverFlow"];
  return tmpStr;
}

我尝试使用Analyzer,它说

  

"对象泄漏:以后在此执行路径中未引用已分配的对象并具有         保留计数为+ 1"

指向调用retrieName的行旁边的行。

我的问题:

对象的保留计数是多少?不应该是2?

,因为:

  1. 第一个引用计数位于retrieveName()

    2.第二个计数是btnsecondClicked()myname变量在哪里?

    ie:myname = retrievedName () - >它不会增加引用次数吗?

4 个答案:

答案 0 :(得分:2)

在此步骤中,您已创建字符串NSString *tmpStr = [[NSString alloc] initWithString "StackOverFlow"];。因此,您已经+1引用计数,因为始终alloc:会返回+1计数的对象。然后你会在哪里发布这个?这就是它显示泄漏的原因。

答案 1 :(得分:1)

从所有权的角度思考 - 专注于您想要说的语义,而不是实现的编写方式。这是面向对象的编程。

任何调用alloc的人都会获得拥有的参考资料。任何打电话给retain的人都会建立所有权。因此,每次调用alloc或retain都必须匹配一个版本 - 如果您希望自动处理,则可以立即匹配releaseautorelease

堆栈上结果的标准是自动释放。这甚至体现在工厂方法(例如[NSString +string])返回这种非拥有参考的规则中。

答案 2 :(得分:1)

不,因为传递一个对象不会对保留计数添加任何内容。

但是,如果你做了

- (IBAction)btnsecondClicked:(id)sender {
   NSString *myname;
   myname  = [retrieveName() retain];
}

然后保留计数将增加到2,因为您明确声明了对该特定对象的所有权。

答案 3 :(得分:1)

- (IBAction)btnsecondClicked:(id)sender {

     NSString *myname;   // nil object, no retain count
     myname  = retrieveName(); // we received the object with retain count 1 (not 2 because you are not sending `retain` to the received object)
} // you exited the function without having global reference on the object, mynames is lost because it was created inside the function, i.e. you leaked at this step 



NSString * retrieveName()
{
  NSString *tmpStr = [[NSString alloc] initWithString "StackOverFlow"]; // retain count is 1
  return tmpStr; // tmpStr returned with retain count of 1
}

现在这里是修复的代码

- (IBAction)btnsecondClicked:(id)sender {

     NSString *myname;
     myname  = retrieveName();  // retain count = 1 and the object is the autorelease pool
}// you exited the function, autorelease pool automatically drained, the object is released, no leak



NSString * retrieveName()
{
  NSString *tmpStr = [[NSString alloc] initWithString "StackOverFlow"];
  return [tmpStr autorelease];  // the object with retain count=1, and added to releasePool
}