最近的SO 讨论使我感到困惑.NSMutableArray原型addObject:是
- (void)addObject:(id)anObject
Run Code Online (Sandbox Code Playgroud)
并id在objc.h中定义为
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
Run Code Online (Sandbox Code Playgroud)
当我将一个NSObject或子类添加到一个时NSMutableArray,它的保留计数会递增,当我从中删除它时,NSMutableArray它会递减.这是否意味着如果一个id type不是一个NSObject或一个子类被添加到一个NSMutableArray,它必须响应保留和释放消息?这个定义id似乎并不强迫这一点.它是一个客观的C指令,任何人id type都应该响应标准的内存管理消息吗?
Rust 可以非常优雅地处理引用计数Rc。社区的许多成员似乎不愿意使用它,而是使用该语言的所有权/借用语义。这使得编写的程序变得更简单,但是除了循环引用之外,还有必要吗?
显然,跨线程事情变得更加复杂,因此为了简化我想要学习的内容,“在单线程应用程序中,除了作为写入时优化之外,是否需要引用计数?” 这是 Rust 技能较高水平的反模式吗?
我一直在评估各种智能指针实现(哇,有很多),在我看来,大多数可以分为两大类:
1)此类别对引用的对象使用继承,以便它们具有引用计数,并且通常实现up()和down()(或它们的等价物).IE,要使用智能指针,您指向的对象必须从ref实现提供的某些类继承.
2)此类别使用辅助对象来保存引用计数.例如,不是将智能指针指向对象,而是实际指向此元数据对象...谁具有引用计数以及up()和down()实现(并且通常为指针提供一种机制)获取指向的实际对象,以便智能指针可以正确实现operator - >()).
现在,1有一个缺点,它强制你想引用的所有对象计数从一个共同的祖先继承,这意味着你不能使用它来引用你无法控制源代码的计数对象至.
2有一个问题,因为计数存储在另一个对象中,如果你有一个指向现有引用计数对象的指针被转换为引用的情况,你可能有一个错误(IE,因为计数不在实际的对象,新的引用没有办法得到计数...引用ref复制构造或赋值是好的,因为它们可以共享count对象,但如果你必须从指针转换,你'完全被冲洗了)...
现在,正如我所理解的那样,boost :: shared_pointer使用了机制2,或类似的东西......那就是说,我不能完全决定哪个更糟糕!我只使用机制1,在生产代码中......有没有人有这两种风格的经验?或许还有另一种方式比这两种方式更好?
这应该是微不足道的,但我似乎无法找到它(除非不存在这样的类!)
什么是智能指针的STL类(或类集)?
UPDATE
感谢您的回复,
我必须说我很惊讶没有标准的实施.
我最终使用了这个:http://archive.gamedev.net/reference/articles/article1060.asp
Python C-API中的标准约定是
函数不会从输入参数(即对象)中窃取引用
返回值和输出参数(即对象)拥有引用
Python C-API中的大多数函数都遵循此约定.但是,也有一些例外.我遇到过以下情况:
从输入参数中窃取引用的函数
PyModule_AddObject
Run Code Online (Sandbox Code Playgroud)
具有返回值的函数或借用引用的输出参数
PyErr_Occurred
PyTuple_GetItem
PyTuple_GETITEM
PyDict_GetItem
PyDict_GetItemString
PyDict_Next
Run Code Online (Sandbox Code Playgroud)
在任何地方都有这样的功能的完整列表吗?编写Python扩展模块时,这样的列表将是一个有用的参考.
我正在尝试在Rust中使用线程之间共享一个可变对象Arc,但是我收到了这个错误:
error[E0596]: cannot borrow data in a `&` reference as mutable
--> src/main.rs:11:13
|
11 | shared_stats_clone.add_stats();
| ^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
Run Code Online (Sandbox Code Playgroud)
这是示例代码:
use std::{sync::Arc, thread};
fn main() {
let total_stats = Stats::new();
let shared_stats = Arc::new(total_stats);
let threads = 5;
for _ in 0..threads {
let mut shared_stats_clone = shared_stats.clone();
thread::spawn(move || {
shared_stats_clone.add_stats();
});
}
}
struct Stats {
hello: u32,
}
impl Stats {
pub fn new() -> Stats {
Stats { hello: 0 …Run Code Online (Sandbox Code Playgroud) 根据我的理解, C++/CX不使用垃圾收集,而是使用引用计数方法.
引用计数的问题在于它不能处理循环.循环通常使用弱引用来解决,例如标准C++中的weak_ptr.
但我无法在C++/CX中找到明确指定弱引用的方法.从那以后我会假设这是由C++/CX本身处理的.我想知道C++/CX将如何解决这个问题.
例如,查看以下代码:
ref class Foo
{
public:
Bar^ bar;
};
ref class Bar
{
public:
Foo^ foo;
};
ref class App
{
public:
virtual void OnLaunched(LaunchActivatedEventArgs^ args)
{
Foo^ foo = ref new Foo();
Bar^ bar = ref new Bar();
foo.bar = bar;
bar.foo = foo;
}
};
Run Code Online (Sandbox Code Playgroud)
C++/CX如何检测此循环?
C++/CX如何解决这个循环?
C++/CX如何决定这些对象中的哪一个应该是"根对象",哪一个应该是"弱引用"?
以下面的例子为例:
- (NSString *)pcen NS_RETURNS_RETAINED {
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef) self, NULL, (CFStringRef) @"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8);
}
Run Code Online (Sandbox Code Playgroud)
把它放在NS_RETURNS_RETAINED那里是正确的吗?
另一个例子:
+ (UIImage *)resizeImage:(UIImage *)img toSize:(CGSize)size NS_RETURNS_RETAINED {
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
[img drawInRect:...];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resizedImage;
}
Run Code Online (Sandbox Code Playgroud)
这似乎更复杂,因为返回的UIImage是"Get"方法的结果.然而,它所获得的图形上下文是在方法的范围内创建的,所以它NS_RETURNS_RETAINED在这里也是正确的吗?
第三个例子:
@property (readonly) NSArray *places;
---
@synthesize places=_places;
---
- (NSArray *)places {
if (_places)
return _places;
return [[NSArray alloc] initWithObjects:@"Unknown", nil];
}
Run Code Online (Sandbox Code Playgroud)
不知道该怎么做,因为返回的对象可以是新创建的.
还有最后一个问题; NS_RETURNS_RETAINED如果返回的对象是自动释放方法的结果,则可能不需要.所以说最后一个例子的回报被修改为
return [NSArray arrayWithObject:@"Unknown"];
什么是最佳实践呢?
memory-management reference-counting objective-c ios automatic-ref-counting
当引用类型的属性具有相互较强的所有权(或具有闭包)时,会发生Swift中的引用循环.
但是,是否有可能只使用值类型的参考周期?
我在游乐场尝试了这个没有成功(错误:不允许递归值类型'A').
struct A {
var otherA: A? = nil
init() {
otherA = A()
}
}
Run Code Online (Sandbox Code Playgroud) reference-counting value-type reference-type automatic-ref-counting swift
据我了解,Swift使用自动引用计数进行垃圾收集.
这让我回到了很多年前,当时我是一名COM程序员.
当对象超出范围时,VB6(以及之前)自动化了引用计数的过程,大多数时候这足以让程序员忘记内存管理.
但是,如果对象之间存在循环,.eg
Car->WheelsCollection contains pointers to wheels
Wheel->CurrentCar constrains a pointer to the car the wheel is currently installed on
Run Code Online (Sandbox Code Playgroud)
然后,当汽车的一个实例超出范围时,它不会被垃圾收集,因为汽车保持车轮活着,并且车轮保持车辆活着.
在Swift中使用哪些程序员模式或其他方式来避免或缓解此问题?
c++ ×3
ios ×2
objective-c ×2
rust ×2
swift ×2
c++-cx ×1
c++03 ×1
concurrency ×1
foundation ×1
nsarray ×1
python ×1
python-c-api ×1
raii ×1
stl ×1
value-type ×1