实际上我会说:是的,Getter 是所有者。因此,任何调用 Getter 的人都不负责释放内存。或者更准确地说,对象本身就是拥有者,但Getter充当了将实例变量传递给其他人的机制。这是对的,还是我弄错了?
4 回答
谈论对象而不是方法,拥有对象更有意义。
很多时候,调用 getter 的对象是被返回对象的所有者,因为返回值是一个实例变量:
- (Foo*) foo { 返回 _foo; // 我的实例变量 }
但是,getter 创建一个已自动释放的临时对象并将其返回也很常见:
- (NSString*) sizeStr { return [NSString stringWithFormat: @"%d", self.size]; }
在这种情况下,该对象(NSString)实际上并没有所有者,除了当前的自动释放池,它会在它退出时释放它。
在(非 GC)Cocoa 编程中要记住的重要规则与所有权本身无关,但与何时引用对象(您必须在某个时候释放)以及何时不相关不。
由于您询问的是使用引用计数系统的 Cocoa,因此不存在“所有者”之类的东西。每个拥有保留引用的人都是部分所有者,负责释放他们的引用。当最后一个引用被释放时,对象被释放。
按照惯例,getter 不会给调用者保留引用,但这并不意味着调用者不能选择显式保留对象。
本质上您是正确的,但这只是惯例问题。只要您的约定始终如一地应用,并且从事该项目的每个人都同意这一点,那么您就是黄金。
你可能会遇到麻烦的地方是,如果调用者缓存了一个指向它从访问器获取的内存的指针,然后对象被破坏,现在指针悬空。
这取决于。
您应该决定对象所有权策略。但一般来说,如果一个对象是另一个对象的子对象(成员),则它所属的对象对其生命周期负责,并且(通常)将其清理为析构函数。
分发内存以由调用者清理通常是不受欢迎的。在 C 中,必须为调用者分配内存的库(例如,X Windows 库或用于数据库客户端的 C API)将分发一个不透明的指针,调用者必须通过调用另一个库函数来销毁该指针:
Window foo = APIcreateWindow();
APIsetupWindow(foo, x, y, z );
AOIshowWindow(foo);
APIdestroyWindow(foo); //forgetting to call this leaks memory
在那个(假设的)代码中,Window
实际上是指向结构的指针的 typedef;APICreateWindow 为结构分配内存,APIdestroyWindow 在做其他 API 簿记之后对其进行免费调用。
在 C++ 中,我们可能会交还一个智能指针,当没有其他东西引用它时它会自行销毁。