c++11 lambda函数及其用法

27 篇文章 0 订阅
为什么需要lambda函数

匿名函数是有函数体,没有函数名。匿名函数最常用的是作为回调函数的值。正因为有这样的需求,c++引入了lambda 函数,你可以在你的源码中内联一个lambda函数,这就使得创建快速的,一次性的函数变得简单了。

代码位置:android8.1:  frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp

 808 template<>
 809 sp<device::V3_2::ICameraDevice>
 810 CameraProviderManager::ProviderInfo::getDeviceInterface
 811         <device::V3_2::ICameraDevice>(const std::string &name) const {
 812     Status status;
 813     sp<device::V3_2::ICameraDevice> cameraInterface;
 814     hardware::Return<void> ret;
//CameraProvider接口getCameraDeviceInterface_V3_x: 由cameraDeviceName获取CameraDevice对象指针
 815     ret = mInterface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
 816         Status s, sp<device::V3_2::ICameraDevice> interface) {                                                                                                                                                                   
 817                 status = s;
 818                 cameraInterface = interface;
 819             });
 820     if (!ret.isOk()) {
 821         ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s",
 822                 __FUNCTION__, name.c_str(), ret.description().c_str());
 823         return nullptr;
 824     }
 825     if (status != Status::OK) {
 826         ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
 827                 name.c_str(), statusToString(status));
 828         return nullptr;
 829     }
 830     return cameraInterface;
 831 }

看看getCameraDeviceInterface_V3_x函数原型:

位置:android8.1: hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp

Return<void> CameraProvider::getCameraDeviceInterface_V3_x(
        const hidl_string& cameraDeviceName, getCameraDeviceInterface_V3_x_cb _hidl_cb)  {
    std::string cameraId, deviceVersion;
//解析cameraDeviceName: deviceVersion与deviceId
    bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
    if (!match) {
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
    }

    std::string deviceName(cameraDeviceName.c_str());
    ssize_t index = mCameraDeviceNames.indexOf(std::make_pair(cameraId, deviceName));
    if (index == NAME_NOT_FOUND) { // Either an illegal name or a device version mismatch
        Status status = Status::OK;
        ssize_t idx = mCameraIds.indexOf(cameraId);
        if (idx == NAME_NOT_FOUND) {
            ALOGE("%s: cannot find camera %s!", __FUNCTION__, cameraId.c_str());
            status = Status::ILLEGAL_ARGUMENT;
        } else { // invalid version
            ALOGE("%s: camera device %s does not support version %s!",
                    __FUNCTION__, cameraId.c_str(), deviceVersion.c_str());
            status = Status::OPERATION_NOT_SUPPORTED;
        }
        _hidl_cb(status, nullptr);
        return Void();
    }

    if (mCameraStatusMap.count(cameraId) == 0 ||
            mCameraStatusMap[cameraId] != CAMERA_DEVICE_STATUS_PRESENT) {
        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
        return Void();
    }

    // Since some Treble HAL revisions can map to the same legacy HAL version(s), we default
    // to the newest possible Treble HAL revision, but allow for override if needed via
    // system property.
    sp<android::hardware::camera::device::V3_2::ICameraDevice> device;
    switch (mPreferredHal3MinorVersion) {
        case 2: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.2
            ALOGV("Constructing v3.2 camera device");
            sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
                    new android::hardware::camera::device::V3_2::implementation::CameraDevice(
                    mModule, cameraId, mCameraDeviceNames);
            if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
                ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
                device = nullptr;
                _hidl_cb(Status::INTERNAL_ERROR, nullptr);
                return Void();
            }
            device = deviceImpl;
            break;
        }
        case 3: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.3
            ALOGV("Constructing v3.3 camera device");
            sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
                    new android::hardware::camera::device::V3_3::implementation::CameraDevice(
                    mModule, cameraId, mCameraDeviceNames);
            if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
                ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
                device = nullptr;
                _hidl_cb(Status::INTERNAL_ERROR, nullptr);
                return Void();
            }
            device = deviceImpl;
            break;
        }
        default:
            ALOGE("%s: Unknown HAL minor version %d!", __FUNCTION__, mPreferredHal3MinorVersion);
            device = nullptr;
            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
            return Void();
    }
    _hidl_cb (Status::OK, device);//调用lambda回调函数
    return Void();
}

基本lambda语法
基本形式如下:
[capture](parameters)->return-type {body}

[]叫做捕获说明符,表示一个lambda表达式的开始。接下来是参数列表,即这个匿名的lambda函数的参数,->return-type表示返回类型,如果没有返回类型,则可以省略这部分。想知道为什么返回类型可以这么表示,这涉及到c++11的另一特性,参见自动类型推导,最后就是函数体部分了。
我们可以这样输出"hello,world"
auto func = [] () { cout << "hello,world"; };
func(); // now call the function

变量捕获与lambda闭包实现
string name;
cin >> name;
[&](){cout << name;}();

lambda函数能够捕获lambda函数外的具有自动存储时期的变量。函数体与这些变量的集合合起来叫闭包。
  • [] 不截取任何变量
  • [&} 截取外部作用域中所有变量,并作为引用在函数体中使用
  • [=] 截取外部作用域中所有变量,并拷贝一份在函数体中使用
  • [=, &foo] 截取外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用
  • [bar] 截取bar变量并且拷贝一份在函数体重使用,同时不截取其他变量
  • [x, &y] x按值传递,y按引用传递
  • [this] 截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。
看到这,不禁要问,这魔法般的变量捕获是怎么实现的呢?原来,lambda是通过创建个小类来实现的。这个类重载了操作符(),一个lambda函数是该类的一个实例。当该类被构造时,周围的变量就传递给构造函数并以成员变量保存起来。看起来跟函数对象很相似。

最后,lambda函数的类型是什么呢,答案是std:function。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值