Closed. This question needs to be more
focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅关注
editing this post的一个问题。
2年前关闭。
Improve this question
我正在写Transpiler,用于教育目的。
我的翻译员从我的语言过渡到C语言。
我现在正在编写闭包语法分析器和代码生成组件。
我看到有人说,C++中的闭包实际上已转换为未命名的结构类型,其中捕获的值作为变量在内部。
Here is the reference。
此代码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将原始捕获列表分配为指针。使它们可以被突变。
附注:请注意,Swift闭包捕获列表仅适用于类或引用类型,但我的意思是此处隐式捕获原始类型。
这是__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;
}
};
我认为关闭完成后立即释放指针变量将太糟糕了。
如果有很多闭包指向变量并且在执行时会发生变化,该怎么办?
如果这些闭包在不同的线程之间传递或执行,该怎么办?
我想出了使用引用计数技术的解决方案。
当创建一个使变量变异的闭包时,该变量将被保留。
当使变量变异的闭包被破坏时,变量将被释放。
没有闭包时,变量将被真正释放。
为了确保线程安全,我将在闭包操纵引用计数技术时锁定和解锁计数器变量地址。
如果还有其他技术,请指导我。
任何语言的任何解释将不胜感激。
目前,我对汇编语言的知识为零。
对于主持人,
因为这个问题是一种研究,所以请您不要将其标记为过于广泛。