关于Objective-C ++ 11:Objective-C ++ 11 – 为什么我们不能将块分配给lambda?

Objective-C++ 11 - Why can't we assign a block to a lambda?

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

Apple LLVM compiler supports additional C++11 features, including lambdas

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

  • lambda可分配给objective-c块:

    1
    2
    3
    4
    5
    void (^block)() = []() -> void {
        NSLog(@"Inside Lambda called as block!");
    };

    block();
  • std::function可容纳一个objective-c块:

    1
    2
    3
    4
    5
    std::function<void(void)> func = ^{
        NSLog(@"Block inside std::function");
    };

    func();
  • 我们无法将Objective-C块分配给lambda:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    auto lambda = []() -> {
        NSLog(@"Lambda!");
    };

    lambda = ^{ // error!
        NSLog(@"Block!");
    };

    lambda();
  • 为什么会这样?考虑到我们上面所看到的,这两者在语义上不应该是等价的吗?


    C++ 11的lambda拷贝赋值运算符是显式禁用的。这不是"语义等价"的问题。它甚至不能重新分配给自己。更不用说一个不相关的类型。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <cstdio>
    #include <type_traits>

    int main() {
        auto lambda1 = []() -> void { printf("Lambda 1!
    "
    ); };
        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,...)调用的类型。由于块支持"invoke操作符",因此它也可以由std::function持有。但是注意Objy-C和C++遵循不同的内存管理方案,所以在EDCOX1 0中存储一个块可能会导致悬空引用。

    lambda可分配给objective-c块:

    • 责怪Sahchandler2:)。不过,它还没有记录在案。

    1:C++ 11节5.1.2/19:

    The closure type associated with a lambda-expression has a deleted (8.4.3) default constructor and a deleted copy assignment operator.

    2:http://llvm.org/viewvc/llvm-project?视图=修订版&修订版=150620


    LAMBDAS有各自的、实现定义的类型,它们对每个lambda都是特定的。下面的代码也是一个错误:

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

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