我正在编写一个用于教育目的的Transpiler。 我的翻译器从我的语言转到C语言 我现在正在编写闭包语法分析器和代码生成组件。
我看到人们说C ++中的闭包实际上是转换为未命名的结构类型,其中捕获的值是内部变量。
此代码
int c = 10;
auto closure = [=] () -> void {
std::cout << c << std::endl;
};
基本上被转化为某种类似的东西,所以他们说。
struct UNNAMED_TYPE_0 {
int c;
void operator() () const {
std::cout << c << std::endl;
}
};
// assume the closure is initialized and variables are assigned
如果有人想在闭包执行时改变int c
,他/她必须将此变量作为ref [&c] () -> void { /* mutation comes here */}
传递。但问题是如果我们在函数内声明int c
并在函数内创建该闭包
function<void()> aFunction() {
int c = 10;
auto closure = [&c] () -> void { c = 100; }
return closure;
}
aFunction() ();
捕获了 int c
但是只要aFunction
堆栈被销毁,int c
也会被销毁。这意味着,如果我们尝试在解除分配的地址上写入,我们可能希望运行segmentation fault(core dumped)
指针错误。
在 Java ,
中// suppose this callback interface exists
public interface VoidCallback {
public void method();
}
public void aMethod() {
int c = 10;
VoidCallback callback = () -> c = 10; /* this gives an error */
// local variables referenced from a lambda expression must be final or effectively final
}
Java处理这样的闭包并确保闭包捕获没有变异(让我们说隐式捕获)。含义Java传递闭包捕获副本而不是ref。对于引用或类类型,仅将Object指针作为副本传递。虽然指针引用不会变异,但您可以改变指针指向的对象内的内容。这与前者基本相同。
Objective-C ,
__block int c = 0;
// they say, this `int c` is allocated in heap instead of stack
// so that it exists until the closure is finished executing.
void (^ closure) (void) = ^void() {
c = 10; // this is valid
// this actually changed the `int c`'s value
};
在 Swift
中var a : Int = 10;
var closure = { [] () -> Void in
a = 10; // this is valid by default
// unless `var a` is declared as `let a`
};
因此,这意味着,Objective-C和Swift将原始捕获列表分配为指针。这样他们就可以变异了。
P.S:请注意,Swift闭包捕获列表仅适用于类或ref类型,但我的意思是隐式捕获原始类型。
这是
__block int c = 0;
// they say, this `int c` is allocated in heap instead of stack
// so that it exists until the closure is finished executing.
void (^ closure) (void) = ^void() {
c = 10; // this is valid
// this actually changed the `int c`'s value
};
与此基本相同
int * c = malloc(sizeof(int));
*c = 0;
void (^ closure) (void) = ^void() {
*c = 10;
if (c) {
free(c);
c = NULL;
}
};
一旦关闭完成就释放指针变量我认为太糟糕了 如果有很多闭包指向变量并且在执行时会发生变异会怎么样? 如果那些闭包传递或在不同的线程中执行会怎么样?
我想出了一个使用参考计数技术的解决方案 当创建一个改变变量的闭包时,该变量将被保留 当一个变量变量的闭包被销毁时,该变量将被释放 如果没有关闭,变量将被真正解除分配。 为了确保线程安全,我会锁定并解锁计数器变量地址,因为闭包操作引用计数技术。
如果还有其他技巧,请指导我 任何语言的任何解释都非常感谢。
目前,我对汇编语言一无所知。
对于版主, 因为这个问题是一种研究,我请求你不要过于宽泛。
答案 0 :(得分:2)
跟着我说:“我正在编写一个用于教育目的的Transpiler。我的翻译器从我的语言转换为C语言。”现在,这意味着您的语言规范定义了它应该如何运作!我们无法告诉您语言应该如何运作。
现在,您已经找到了许多选项:
with
得到类似的东西,只是为了完整性),所以这个没有任何区别。这些语言给你带来了开销,以保证你没有任何悬空引用(也许即使你真的不需要它)。现在,首先要确定哪一种最适合您语言的对象模型。只有这样,问题就出现了如何最好地实现它。关于实现,有许多不同的方法。使用引用计数器是一个(使用无锁,原子操作实现),使用链表是另一个,或使用垃圾收集器。