gpt4 book ai didi

objective-c - 在 Objective-C 中实现 Go 中的 ‘defer’ 语句?

转载 作者:IT王子 更新时间:2023-10-29 01:28:08 25 4
gpt4 key购买 nike

今天看了Go语言的defer语句:

A defer statement pushes a function call onto a list. The list of saved calls is executed after the surrounding function returns. Defer is commonly used to simplify functions that perform various clean-up actions.

我认为在 Objective-C 中实现这样的东西会很有趣。你知道怎么做吗?我想到了分派(dispatch)终结器、自动释放对象和 C++ 析构函数。

自动释放的对象:

@interface Defer : NSObject {}
+ (id) withCode: (dispatch_block_t) block;
@end

@implementation Defer
- (void) dealloc {
block();
[super dealloc];
}
@end

#define defer(__x) [Defer withCode:^{__x}]

- (void) function
{
defer(NSLog(@"Done"));

}

自动释放对象似乎是唯一至少会持续到函数结束的解决方案,因为其他解决方案会在当前作用域结束时触发。另一方面,它们可以在内存中停留更长时间,这会带来麻烦。

Dispatch 终结器是我的第一个想法,因为 block 存在于堆栈中,因此我可以轻松地在堆栈展开时执行某些操作。但是在浏览了文档之后,我似乎无法将一个简单的“析构函数”函数附加到 block 上,对吗?

C++ 析构函数大致相同,我会创建一个基于堆栈的对象,其中包含一个在析构函数运行时要执行的 block 。这会带来将普通 .m 文件转换为 Objective-C++ 的丑陋缺点吗?

我并没有真正考虑在生产中使用这些东西,我只是对各种解决方案感兴趣。你能想出一些有用的东西,没有明显的缺点吗?基于范围和基于功能的解决方案都会很有趣。

最佳答案

如果您可以使用 C++,请查看 Boost 的 Scope Exit图书馆。


如果您不介意在函数的开头和结尾输入 2 个额外的单词,您可以使用 @finally block 。

#define SCOPE               {id _defered_actions__=[[NSMutableArray alloc]init];@try{
#define END_SCOPE }@finally{for(void(^action)()in[_defered_actions__ reverseObjectEnumerator])action();[_defered_actions__ release];}}
#define DEFER_COPY(_code__) {id _blk__=[^{_code__;}copy];[_defered_actions__ addObject:_blk__];[_blk__ release];}
#define DEFER(_code__) ([_defered_actions__ addObject:(^{_code__;})])

使用示例:

@interface XXObject : NSObject {
}
-(int)factorial:(int)x;
@end

@implementation XXObject
-(int)factorial:(int)x { SCOPE

printf("begin foo:%d\n", x);
DEFER( printf("end foo:%d\n", x) );

if (x > 0)
return x * [self factorial:x-1];
else if (x == 0)
return 1;
else {
@throw [NSException exceptionWithName:@"NegativeFactorialException"
reason:@"Cannot call factorial on negative numbers"
userInfo:nil];
return 0;
}

END_SCOPE }

-(void)dealloc {
printf("%p has been released.\n", self);
[super dealloc];
}
@end




void do_stuff() { SCOPE

__block XXObject* x = [[XXObject alloc] init];
DEFER({
printf("releasing %p.\n", x);
[x release];
});


int i;
for (i = 2; i >= -1; -- i) {
// use DEFER_COPY to retain the local variable 'i' and 'fact'
int fact = [x factorial:i];
DEFER_COPY( printf("%d! == %d\n", i, fact) );
}

END_SCOPE }




int main () {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

@try {
do_stuff();
} @catch(NSException* e) {
// note that the @finally statements might not be called in 64-bit if we
// left the exception uncaught.
NSLog(@"%@", e);
}
[pool drain];
return 0;
}

应该打印:

begin foo:2begin foo:1begin foo:0end foo:0end foo:1end foo:2begin foo:1begin foo:0end foo:0end foo:1begin foo:0end foo:0begin foo:-1end foo:-10! == 11! == 12! == 2releasing 0x100116500.0x100116500 has been released.2011-02-05 23:06:21.192 a.out[51141:903] Cannot call factorial on negative numbers

关于objective-c - 在 Objective-C 中实现 Go 中的 ‘defer’ 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4883760/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com