【问题标题】:Using C++11 lambda functions in ARC ObjectiveC++ - how to do it properly?在 ARC ObjectiveC++ 中使用 C++11 lambda 函数 - 如何正确执行?
【发布时间】:2012-10-26 07:22:16
【问题描述】:

我有一个 ObjectiveC++ 项目。在 ObjectiveC 上下文中,我使用 ARC 和 iPhoneSDK 6。在 C++ 中,我使用 C++11 编译器。

C++11 中的 Lambda 函数使用引用捕获变量。 ObjectiveC 并不真正支持这个概念,通过“尝试和错误”我想出了以下解决方案。有没有我不知道的陷阱?

这个问题有更好的解决方案吗?

typedef std::function<void ()> MyLambdaType;

...
// m_myView will not go away. ARC managed.
UIView * __strong m_myView;

...
// In Objective C context I create a lambda function that calls my Objective C object
UIView &myViewReference = *m_myView;
MyLambdaType myLambda = [&myViewReference]() {
    UIView *myViewBlockScope = &myViewReference;
    // Do something with `myViewBlockScope`
}

..
// In C++11 context I call this lambda function
myLambda();

【问题讨论】:

  • AFAIK 块仅是 ObjectiveC,或者?如何将块传递给 C++?
  • MyLambdaType myLambda = [m_myView]() { // Do something with m_myView } 不起作用吗?
  • @newacct AFAIK 在这种情况下会创建一个副本。见这里:en.cppreference.com/w/cpp/language/lambda
  • @LarsSchneider:是的,m_myView 的副本,指向您的对象的指针。这不是你想要的吗?
  • @newacct 我非常愚蠢。你是对的。你想创建一个“答案”,以便我给你答案吗?

标签: objective-c lambda c++11 automatic-ref-counting objective-c-blocks


【解决方案1】:

最简单的做法是让 lambda 捕获对象指针变量m_myView(我从你的 sn-p 假设这是一个局部变量),并在 lambda 中正常使用它:

MyLambdaType myLambda = [m_myView]() {
    // Do something with `m_myView`
}

唯一需要关注的是m_myView 的内存管理。一般来说,lambda 需要在创建时保留m_myView,并在销毁时释放它(就像块一样;因为 lambda 可以在m_myView 不存在的范围内使用)。

阅读 ARC 文档,我没有看到具体提到这种情况,但我相信它应该正确处理它,因为 (1) 捕获的 C++11 lambda 变量存储为匿名类的字段,在构造 lambda 时将其初始化为捕获的值,并且 (2) ARC 在构造和销毁时正确处理 C++ 类的 Objective-C 对象字段的保留和释放。除非它特别说明了有关 lambdas 的相反内容,或者存在编译器错误,否则我看不出它不应该工作的原因。

【讨论】:

  • 这绝对有效。棘手的是,在 C++11 lambda 术语中,m_myView 在这里被“按值”捕获。如果您“通过引用”捕获它(例如:[&amp;m_myView](){...}),则对象 m_myViewNOT 被 ARC 保留。如果您考虑一下,这很有意义(即,当您告诉 C++ 通过引用捕获 m_myView 时,C++ 正在捕获对指针的引用,而不是对对象的引用),但术语可能有点混乱。
  • @ipmcc:是的。这对于一般 C++11 lambda 中的引用捕获来说是正确的。如果您在 C++11 lambda 中通过引用捕获,那么您不能在这些捕获变量的范围之外使用该 lambda。
  • 看来 m_myView 使用的内存没有被 ARC 释放。我的代码中每隔几毫秒就会收到很多回调,而且我的内存在稳步跳跃。对于在 lambda 函数内创建的 Objective-C 对象也是如此。它们也在泄漏。
  • @AshishAwaghad 您需要确保您的 m_myView 没有强烈引用 lambda。你有内存泄漏的事实可能是因为你在那里进入了一个保留圈。
  • 我也泄漏了一个被 lambda 捕获的 (NSData) 对象。通过将 lambda 中的语句包装在 @autoreleasepool 块中来修复泄漏。
猜你喜欢
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-01
  • 2013-03-29
相关资源
最近更新 更多