弱和强 属性 实施
Weak and strong property implementation
我想更好地理解 strong
和 weak
指针的实现,并且我想出了关于它们的 setter 方法的假设(如果我错了请纠正我) .
首先,强指针,看起来像:
- (void)setObj:(NSObject*)Obj // Setting Strong Obj
{
//First, check either we trying to set old value again
if (_Obj == Obj)
{
return;
}
NSObject* oldObj = _Obj;
_Obj = [Obj retain];
[oldObj release];
// Set pointer to old "chunk" of memory, containing old value,
// assign new value to backed instance variable and release
// old value
}
那是我的构造假设,强 setter 可能看起来像。所以,我的第一个问题是 - 我的假设是否正确?
第二,弱引用。我想,它看起来应该相似,但不包括 retain
.
- (void)setObj:(NSObject*)Obj // Setting Weak Obj
{
if (_Obj == Obj)
{
return;
}
NSObject* oldObj = _Obj;
_Obj = Obj; // setting value without incrementing reference count
[oldObj release];
}
关于 weak
参考工作的假设是否正确?
好的,还有一个问题。考虑这样的情况(在手动内存管理中):
- (void)testFunc
{
strongObj = val; // Retain count about >= 2
weakObj = val; // Retain count about >=1
}
// Now strongObj lives in memory with value of val, with retain count >=1
// weakObj is destroyed, since after end of a scope (function body) it retain count decreased by 1
所以,其实我想知道,retain count
是否每次递减,当拥有变量的方法完成时?
我知道这个问题对很多开发人员来说都很熟悉,但是,在那种情况下我想澄清一下。谢谢。
你的强执行是正确的。
弱者错了。如果您之前未保留该值,则不允许释放该值。您只需在此处设置新值而无需发出内存管理调用。
话又说回来,那不是真的很弱,而是赋值。 weak 的特殊之处在于引用被清零,被引用的对象被释放。
对于第一个和第二个问题,我参考了@rmaddy 的评论和 Christian 的回答。
So, actually i want to know, whether retain count decremented each time, when method that own variable finishes?
首先,我想更准确地说:当你说 "when method that own a variable finishes" 时,你可能指的是 "when a local strong reference variable of automatic storage class loses its extent"。这并不完全相同。但这可能是你想说的。 ("A usual local var.")
在这种情况下,引用的对象被释放是正确的。
但幕后的事情更难。即:如果返回局部变量(再次更精确:引用的对象)会发生什么?在这种情况下会发生什么,如果该方法是所有权转让或不是?
基本问题是自动引用计数必须正式考虑边缘情况,即使在 "usual" 代码中也不能破坏。人类开发人员可以说:"Oh, there is a very special situation the code can break, but I know that this never happens." 编译器不能。所以 ARC 通常会创建非常多的内存处理调用。幸运的是,其中许多都被优化掉了。
如果你想深入了解在什么情况下做了什么,你有两个好方法:
阅读clang's documenation,目前比Apple的更精确,但更复杂。
在单独的文件中创建一个 class 来实现手动引用计数的方法(-retain
、-release
、…)并记录执行。然后使用手动引用计数对其进行编译,这可以通过编译器标志实现。在 ARC 代码中使用 class。您将看到 ARC 的作用。 (你不应该依赖结果,因为它们是优化的主题,策略在未来可能会改变。但它是理解 ARC 工作原理的好工具。)
从气球的角度考虑强引用和弱引用可能会有所帮助。
只要至少有一个人拉着系在气球上的一根绳子,气球就不会飞走。持有字符串的人数是保留计数。当没有人抓住一根绳子时,气球就会飞走(dealloc)。很多人都可以用绳子系同一个气球。您可以 get/set 使用强引用和弱引用对被引用对象的属性和调用方法。
强引用就像抓住气球上的一根绳子。只要你拉着气球上的绳子,它就不会飞走。
弱引用就像看气球。你可以看到它,访问它的属性,调用它的方法,但是你没有那个气球的字符串。如果拉着绳子的人都松手,气球就会飞走,你就不能再靠近了。
我想更好地理解 strong
和 weak
指针的实现,并且我想出了关于它们的 setter 方法的假设(如果我错了请纠正我) .
首先,强指针,看起来像:
- (void)setObj:(NSObject*)Obj // Setting Strong Obj
{
//First, check either we trying to set old value again
if (_Obj == Obj)
{
return;
}
NSObject* oldObj = _Obj;
_Obj = [Obj retain];
[oldObj release];
// Set pointer to old "chunk" of memory, containing old value,
// assign new value to backed instance variable and release
// old value
}
那是我的构造假设,强 setter 可能看起来像。所以,我的第一个问题是 - 我的假设是否正确?
第二,弱引用。我想,它看起来应该相似,但不包括 retain
.
- (void)setObj:(NSObject*)Obj // Setting Weak Obj
{
if (_Obj == Obj)
{
return;
}
NSObject* oldObj = _Obj;
_Obj = Obj; // setting value without incrementing reference count
[oldObj release];
}
关于 weak
参考工作的假设是否正确?
好的,还有一个问题。考虑这样的情况(在手动内存管理中):
- (void)testFunc
{
strongObj = val; // Retain count about >= 2
weakObj = val; // Retain count about >=1
}
// Now strongObj lives in memory with value of val, with retain count >=1
// weakObj is destroyed, since after end of a scope (function body) it retain count decreased by 1
所以,其实我想知道,retain count
是否每次递减,当拥有变量的方法完成时?
我知道这个问题对很多开发人员来说都很熟悉,但是,在那种情况下我想澄清一下。谢谢。
你的强执行是正确的。
弱者错了。如果您之前未保留该值,则不允许释放该值。您只需在此处设置新值而无需发出内存管理调用。
话又说回来,那不是真的很弱,而是赋值。 weak 的特殊之处在于引用被清零,被引用的对象被释放。
对于第一个和第二个问题,我参考了@rmaddy 的评论和 Christian 的回答。
So, actually i want to know, whether retain count decremented each time, when method that own variable finishes?
首先,我想更准确地说:当你说 "when method that own a variable finishes" 时,你可能指的是 "when a local strong reference variable of automatic storage class loses its extent"。这并不完全相同。但这可能是你想说的。 ("A usual local var.")
在这种情况下,引用的对象被释放是正确的。
但幕后的事情更难。即:如果返回局部变量(再次更精确:引用的对象)会发生什么?在这种情况下会发生什么,如果该方法是所有权转让或不是?
基本问题是自动引用计数必须正式考虑边缘情况,即使在 "usual" 代码中也不能破坏。人类开发人员可以说:"Oh, there is a very special situation the code can break, but I know that this never happens." 编译器不能。所以 ARC 通常会创建非常多的内存处理调用。幸运的是,其中许多都被优化掉了。
如果你想深入了解在什么情况下做了什么,你有两个好方法:
阅读clang's documenation,目前比Apple的更精确,但更复杂。
在单独的文件中创建一个 class 来实现手动引用计数的方法(
-retain
、-release
、…)并记录执行。然后使用手动引用计数对其进行编译,这可以通过编译器标志实现。在 ARC 代码中使用 class。您将看到 ARC 的作用。 (你不应该依赖结果,因为它们是优化的主题,策略在未来可能会改变。但它是理解 ARC 工作原理的好工具。)
从气球的角度考虑强引用和弱引用可能会有所帮助。
只要至少有一个人拉着系在气球上的一根绳子,气球就不会飞走。持有字符串的人数是保留计数。当没有人抓住一根绳子时,气球就会飞走(dealloc)。很多人都可以用绳子系同一个气球。您可以 get/set 使用强引用和弱引用对被引用对象的属性和调用方法。
强引用就像抓住气球上的一根绳子。只要你拉着气球上的绳子,它就不会飞走。
弱引用就像看气球。你可以看到它,访问它的属性,调用它的方法,但是你没有那个气球的字符串。如果拉着绳子的人都松手,气球就会飞走,你就不能再靠近了。