为什么需要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。