16

所以,我刚刚升级到 Xcode 4.4,我在更新日志中注意到:

Apple LLVM 编译器支持其他 C++11 功能,包括 lambda

太棒了!所以我开始编码,我发现了一些事情:

  1. Lambda 可分配给 Objective-C 块:

    void (^block)() = []() -> void { 
        NSLog(@"Inside Lambda called as block!");
    };
    
    block();
    
  2. std::function可以容纳一个 Objective-C 块:

    std::function<void(void)> func = ^{
        NSLog(@"Block inside std::function");
    };
    
    func();
    
  3. 我们不能将 Objective-C 块分配给 lambda:

    auto lambda = []() -> {
        NSLog(@"Lambda!");
    };
    
    lambda = ^{ // error!
        NSLog(@"Block!");
    };
    
    lambda();
    

为什么是这样?鉴于我们在上面看到的,这两者在语义上不应该是等价的吗?

4

2 回答 2

15

C++11 的 lambda 的复制赋值运算符被明确禁用1。这不是“语义等价”的问题。它甚至不能分配回自己。更不用说不相关的类型了。

#include <cstdio>
#include <type_traits>

int main() {
    auto lambda1 = []() -> void { printf("Lambda 1!\n"); };
    lambda1 = lambda1;  // error: use of deleted function ‘main()::<lambda()>& main()::<lambda()>::operator=(const main()::<lambda()>&)’
    return 0;
}

std::function可以容纳一个 Objective-C 块。

  • std::function可以保存任何可以调用的类型f(a,b,c,...)。由于块支持“调用运算符”,它也可以由std::function. 但是请注意,Objective-C 和 C++ 遵循不同的内存管理方案,因此在 astd::function中长时间存储块可能会导致悬空引用。

Lambda 可分配给 Objective-C 块:

  • 责备SAHChandler 2 :)。不过,它还没有记录在案。

1:C++11 §5.1.2/19:

与lambda 表达式关联的闭包类型具有已删除的 (8.4.3) 默认构造函数和已删除的复制赋值运算符。

2: http://llvm.org/viewvc/llvm-project?view=rev&revision= 150620

于 2012-07-26T12:47:44.243 回答
3

Lambda 有自己的、实现定义的类型,这些类型特定于每个 lambda。下面的代码也是一个错误:

auto l1=[](){return 1;}
auto l2=[](){return 2;}
l1=l2; //Error

std::function是一个包装器,旨在保存任何可调用类型;您应该使用它来保存可能是不同类型的可调用对象。

于 2012-07-26T12:46:24.393 回答