【问题标题】:C++ lambda implementation in runtime运行时的 C++ lambda 实现
【发布时间】:2013-12-03 12:30:08
【问题描述】:

在 Objective-C 中,我们知道块在运行时有 3 个实现。

  1. NSGlobalBlock - 在运行时是单例的,它是在我们不使用堆栈变量的值的情况下创建的。
  2. NSStackBlock - 不是单例的,它是在栈上分配的(不是在堆上),它是在我们使用一些栈变量时创建的。
  3. NSMallocBlock - 在堆上分配,当我们想要将块存储为 ivar 或某个类的属性时使用,或者在堆 f.e. 中的任何位置。 @property (nonatomic, copy) MyBlockType myBlock; 或当我们使用 Block_copy() 函数时。这非常重要,因为 NSMallocBlock 会保留上下文中的对象,如果我们不正确使用块,这一事实可能会产生一些拥有周期。

所以,我的问题是:“我在哪里可以找到 C++ lambdas 运行时的完整解释,以及编译器如何处理它们?或者你能解释一下吗?使用 C++ lambdas 进行内存管理有什么具体问题吗?lambdas 在哪里?分配,在堆上还是在堆栈上?”

【问题讨论】:

  • "并且它是在我们不使用 __block 修饰符更改堆栈变量的值的情况下创建的。"否。NSGlobalBlock 用于不是 闭包 的块,即不从外部范围捕获任何局部变量。 “它是在我们对某些堆栈变量使用 _block 修饰符时创建的。”不,同样,它适用于任何 闭包 的块,即使用来自外部范围的局部变量。它不必是 __block 变量。
  • @newacct 你说得对,NSGlobalBlock 只能使用静态变量,谢谢!

标签: c++ objective-c lambda objective-c-blocks objective-c++


【解决方案1】:

Lambdas 实现是特定于编译器的。

标准没有指定内存分配的位置,但根据经验,它们大致相当于old-school functors,并且它们及其捕获的值被复制到堆栈中,就像任何普通物体一样。

例如

std::vector<int> v{10,11,12,13};
std::for_each(v.begin(), v.end(), [](int& i) {i++;});

将只是一个无状态函数。

或者,

std::vector<int> v{10,11,12,13};
int C = 10;
int D = 20;
std::for_each(v.begin(), v.end(), [C,&D](int& i) {i += C + D;});

相当于在堆栈上构造了一个仿函数,其中包含C 的副本,并引用D 作为其成员(但可能会被优化掉)。

真正将 lambda 对象放在堆上的唯一时间是当它转换为 std::function 时,它是如何完成的取决于编译器对 std::function 的实现。

void g(const std::function& f);
// ...
auto f = [=](int& i){i += C;}; // still on the stack (compiler-specific type)
g(f); // std::function constructed, possibly on the heap

【讨论】:

    猜你喜欢
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多