Line 1: First.h
Line 2: @property (nonatomic, retain) NSString *name;
Line 3: First.m
Line 4: @synthesize name;
Line 5: -(void)viewDidLoad()
Line 6: {
Line 7: name = [NSString stringwithString@"Hello"];
Line 8: OR
Line 9: self.name = [NSString alloc]initwithString@"Hello"];
Line 10: OR
Line 11: }
Line 12:-(void)dealloc()
Line 13: {
Line 14: [name release];
Line 14: }
问题1:
如果我遵循第7行,一切都很好,如果我使用第9行内存泄漏是存在的。因为我知道自我指向当前对象,如果我使用self.object或简单地对象没有更多的区别。
问题2:如果我使用
@synthesize name = _name;
然后哪一个用于设置name的值,哪一个用于获取值?
之间的区别name = [NSTring stringWithString@"hello"];
OR
self.name = [NSString stringwithString@"hello"];
OR
_name = [NSString stringwithString@"Hello"];
问题3:
如果我创建任何属性,则需要在内存中分配,因为我分配了显示内存泄漏。
有什么建议吗?
答案 0 :(得分:2)
要回复第一个问题:您会收到泄漏,因为使用alloc
方法初始化字符串您保留创建的对象,但之后不会释放该对象,所以你获取泄漏,同时使用stringwithString
创建字符串,您将获得自动释放池自动释放的自动释放对象。请注意,在第9行的示例中,您正在初始化对象并将其传递给属性的setter,如果您使用了ivar,情况会有所不同......
要回复第二个问题:您正在综合属性名称并将其与名为_name
的内部变量(ivar)相关联,因此您可以在班级内部访问该值。使用ivar _name
的财产。
我强烈建议您阅读有关内存管理的苹果文档here。
答案 1 :(得分:2)
问题1:如果我遵循第7行,一切都很好,如果我使用第9行内存泄漏就在那里。正如我所知,seld指向当前对象,如果我使用seld.object或简单对象没有更多的区别。
Line 7: name = [NSString stringwithString@"Hello"];
Line 8: OR
Line 9: self.name = [NSString alloc]initwithString@"Hello"];
在第7行,您使用的是便利构造函数,它返回一个自动释放的对象,并将对象直接分配给您的name
ivar;现在,可以将自动释放的对象分配给retain属性,但是将自动释放的对象直接分配给ivar而不明确地保留它是不正确的:
name = [[NSString stringWithString:@"Hello"] retain];
在第9行,您使用的是alloc / init,它为您提供了一个保留对象:将这样的对象直接分配给ivar是正确的,但您应该在分配到retain属性之前自动释放它,例如:
self.name = [[[NSString alloc]initWithString:@"Hello"] autorelease];
您可以根据对象保留计数对此进行推理:
一个便利构造函数会将保留计数设置为1,但稍后会通过框架的release
调用自动减少;
除非您明确致电release
,
当对象保留计数变为0时,它将被取消分配。
保留计数方面的推理只是一种了解内存管理的整个问题并了解框架内部正在发生的事情的方法;但是,这绝不是分析对象生命周期的正确方法。
然后哪一个用于设置name的值,哪一个用于获取值? name = [NSTring stringWithString @“hello”]之间的区别; OR self.name = [NSString stringwithString @“hello”]; OR _name = [NSString stringwithString @“Hello”];
name = [NSTring stringWithString@"hello"];
和
_name = [NSString stringwithString@"Hello"];
在给出的两种情况下,是一样的。这将绕过属性设置器(/ getter)方法并直接分配给ivar。在这种情况下,您的应用程序迟早会崩溃,因为您直接将自动释放的对象分配给ivar。这是正确的:
_name = [[NSString stringwithString@"Hello"] retain];
或
_name = [[NSString alloc] initwithString@"Hello"];
请注意,在您将ivar声明为_name
的程序中,您无法使用name
来引用它;您可以使用name
直接引用ivar,如果您声明仅该属性而未明确指定ivar,就像您对问题1所做的那样(在这种情况下,name
将是由编译器为您自动生成的ivar。
另一方面:
self.name = [NSString stringwithString@"hello"];
将使用属性访问器方法(实际上是setter);因为你的属性被声明为retain
,所以可以为它分配由方便构造函数stringWithString:
返回的自动释放变量。
问题3:如果我创建了任何属性,那么就需要在momory中分配,因为我已经分配了这些内容。
这对我来说并不是很清楚......
有关内存管理基本知识的好文档是:Memory Management Policy以及Apple高级内存管理编程指南中的Practical Memory Management。
答案 2 :(得分:0)
首先是 MRC 概念的背景,仅的摘要:
内存管理完全是关于所有权;只要你拥有一个对象它就会存在,在放弃所有权后的某个时候,对象将被销毁。您维护到对象的任何引用实际上都是无效的,一旦您放弃了所有权,就不应该使用它。
所有权不是独占的,而是遵循共享模式,在任何给定时间都可以有多个所有者,并且只有当某个对象没有所有者时才会变为可用被摧毁。
如果您只需要暂时使用某个对象,例如在单个代码块中,您并不总是需要拥有所有权。这部分是由于所有权和被放弃的结果;而不是立即放弃所有权,您可以要求所有权在以后放弃。
稍后在执行应用程序的某些点发生,除非手动添加任何此类点,否则在执行每个循环后,有一个这样的点循环。
所有权通过retain
调用或调用返回您拥有的对象的方法来声明 - 最常见的是alloc
,还有copy
和其他人。通过调用release
,所有权放弃;并使用对autorelease
的调用稍后放弃。
问题1:
Line 7: name = [NSString stringWithString:@"Hello"];
Line 8: OR
Line 9: self.name = [[NSString alloc] initWithString:@"Hello"];
第7行的右侧(RHS)返回对不拥有的对象的引用。左侧(LHS)将此引用分配给实例变量 name
。您现在已经存储了对您不拥有的内容的引用,这是不好的,因为在将来任何时候对象的所有者可能放弃所有权,对象被销毁,并且您的引用无效在name
。课程:*不要在实例变量中存储对您不拥有的对象的引用“。
另一方面,第9行的RHS返回对拥有的对象的引用。但是,LHS使用属性调用 self.name
来存储引用,并且还拥有所有权,因为它是retain
属性 - 您现在拥有它两次, this是坏的,但如果不同的方式;除非你还放弃了两次所有权,你可能不会这样做,否则该对象将始终拥有一个所有者并将永远存在,通常称为泄漏。
如果你交换代码:
Line 7a: name = [[NSString alloc] initWithString:@"Hello"];
Line 8a: OR
Line 9b: self.name = [NSString stringWithString: @"Hello"];
那么它会做你期望的。第7a行的RHS返回您拥有的对象引用,LHS将其存储在由属性 name
管理的实例变量 name
中
第9a行的RHS返回您不拥有的对象引用,但LHS使用属性调用,并且该属性具有retain
属性所有权并且存储引用在实例变量中 name
是一个拥有的对象。
在任何一种情况下,当前实例(self
)被销毁,因为属性name
具有实例变量retain
对任何对象引用的name
属性所有权将被放弃。
问题2
使用的影响是什么:
@synthesize name = _name;
这只是意味着属性 name
将使用实例变量 _name
而不是name
。在您的代码段中,您永远不会声明name
或_name
,因此@synthesize
会自动声明这两者;因此,根据name
,只有_name
或@synthesize
实例变量。因此问题2的答案是问题1的答案,每个对实例变量name
的引用都被_name
取代。
问题3
如果我理解这个问题,并且我不确定,那么问题1的答案就会涵盖。
HTH