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

What is the reference count of an object in the following program?

提问人:Whoami 提问时间:7/19/2014 最后编辑:BinarianWhoami 更新时间:7/19/2014 访问量:86

问:

1) 禁用 ARC。

2) 我有以下代码:

- (IBAction)btnsecondClicked:(id)sender {

     NSString *myname;
     myname  = retrieveName();
}


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

我尝试使用分析仪,它说

“对象泄漏:分配的对象稍后不会在此执行路径中引用,并且具有 保留计数为 +1”

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

我的问题:

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

因为:

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

    2.第二个计数在 中,其中变量成立?btnsecondClicked()myname

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

IOS 目标-C iOS5 IOS4

评论

0赞 albertamg 7/19/2014
应根据对象所有权规则重命名方法,以指示调用方拥有返回的对象。autoreleasetmpStrretrieveName

答:

2赞 Mani 7/19/2014 #1

在此步骤中,您已经创建了字符串。所以你有 +1 个引用计数,因为总是返回 +1 计数的对象。那你将在哪里发布这个?这就是为什么它显示为泄漏。NSString *tmpStr = [[NSString alloc] initWithString "StackOverFlow"];alloc:

1赞 Tommy 7/19/2014 #2

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

无论谁来电,都会得到一个拥有的参考。任何打电话的人都会建立所有权。因此,对 alloc 或 retain 的每个调用都必须与发布相匹配 - 无论是 immediate 还是 an (如果您希望它自主处理)。allocretainreleaseautorelease

堆栈上结果的规范是自动发布。这甚至被载入了工厂方法(例如 返回这样一个非拥有引用。[NSString +string]

1赞 galrito 7/19/2014 #3

否,因为传递对象不会对保留计数增加任何内容。

但是,如果你这样做了

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

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

1赞 Basheer_CAD 7/19/2014 #4
- (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
}