lambda 表达式
plugins/predict/src/predictor.cc
select_connection_ = context->select_notifier().connect(
[this](Context* ctx) { OnSelect(ctx); });
lambda 是 C++ 11 中的特性,它是一种匿名函数。
语法:
[捕获列表](参数列表) -> 返回值 { 函数体; };
- 编译器可简单的推导出 返回值 的类型,当可推导时,可省略
-> 返回值
的声明。 - 当函数没有参数列表时,参数列表可省略,即
()
可省略。 - 捕获列表
[]
与函数体{}
任何情况下都必须存在。 - 函数体后分号,即
{};
,不能省略
捕获列表
[]
: 表示不捕获任何变量[&]
: 表示捕获外部作用域中全部变量,并作为引用在函数体内使用。 注意:程序必须保证,调用时,引用的变量没有超过其作用域。[=]
: 表示捕获外部作用域中全部变量,并作为值在函数体内使用。 值表示:只能读取,不能赋值。[this]
: 用于类中,表示捕获当前类的this
指针,目的是让 lambda 函数具有当前类成员函数相同的访问权限。 注意:- 如果使用了
[&]
[=]
,那么默认就相当于捕获了this
。 [=]
或者[this]
,只可读取当前类的成员变量,不可修改,如需修改,请使用[&]
- 如果使用了
- 变量的值捕获
[变量名]
与引用捕获[&变量名]
[变量名]
: 值捕获,不能修改变量的值。[&变量名]
: 引用捕获,可修改变量的值。
- 组合捕获
[=, &变量名]
: 按值捕获外部全部变量,但按引用捕获后面的变量。[&, 变量名]
: 按引用捕获外部全部变量,但按值捕获后面的变量。
lambda 中的 mutable
语法:
[捕获列表](参数列表) mutable -> 返回值 { 函数体; };
注意:有了 mutable
修饰后,参数列表的括号是不能省略。
使用 mutable
修饰后,函数体内可修改外部作用域下的常量属性的值。
smart pointer 智能指针
智能指针是为了防止内存泄漏,而将内存的释放工作交给智能指针处理。
当不使用智能指针时,需要使用 new
与 delete
申请和释放内存,且它俩是必须成对使用。
malloc
与 free
是 C 语言中的内存申请与释放的关键字。new
与 delete
是 C++ 中的内存管理关键字。
智能指针是对 new
关键字返回的指针的包装,它可以自动释放申请的内存。
C++ 标准库中有 4 种智能指针:std::auto_ptr
,std::unique_ptr
,std::shard_ptr
,std::weak_ptr
。
注意:std::auto_ptr
是 C++ 98 版本中的智能指针,在 C++ 11 中已经完全被 std::unique_ptr
替代,所以不要在使用 std::auto_ptr
。
unique_ptr
:是独占式指针,同一时间有且只有一个指针指向该对象,当然,对象的所有权是可以移交出去的。 shared_ptr
:是共享式指针,多个指针可以指向同一个对象,当最后一个指针被销毁时,则指向的对象也会被释放。 weak_ptr
: 是用来辅助 shared_ptr
指针。
shared_ptr
shared_ptr
工作机制是 引用计数。当指针指向的对象需要被共享时,应该使用 shared_ptr
。
语法:
std::shared_ptr<指向类型> 指针名;
如:
// 形式1:
std::shared_ptr<int> p1(new int(100));
// 错误的形式
// std::shared_ptr<int> p2 = new int(100);
// 形式2: 使用标准库中的 make_shared 函数构建
std::shared_ptr<int> p3 = std::make_shared<int>(100);
注意:使用 std::make_shared
函数构建的 shared_ptr 指针不能自定义删除器。
use_count()
返回指针引用计数的数量。用于调试,效率不高。unique()
返回 bool 值,表示是否有指针指向该对象。reset()
- 不带参数时, 即
p1.reset()
,对象的应用计数减1,同时当前指针指向nullptr
。 - 带
new
参数,如p1.reset(new int(200))
,释放指针原指向的对象,同时指针指向新的对象。 - 空指针使用
reset(new xx)
初始化,如std::shared_ptr<int> p; p.reset(new int(100))
。
- 不带参数时, 即
*
解引用:*指针
解引用指针指向的对象get()
返回智能指针中保存的指针。std::swap(p1, p2)
: 交换两个指针指向的对象= nullptr
将指针置为空if (智能指针)
:判断指针是否指向一个对象。
删除器
语法:std::shared<int> p1(new int(100), 指定删除器)
默认删除器不支持删除一些如数组对象,这时就需要指定默认删除器。
std::shared_ptr<int[]> p(new int[10], [](int *p){
delete[] p;
});
p.reset();
可以将 default_delete<T>()
类模板作为默认删除器。
std::shared_ptr<A> p(new A[10], std::default_delete<A[]>());
p.reset();
weak_ptr
与 Swift 中的 weak
含义相同,指不改变对象的引用计数,则控制不了对象的生命周期。
std::weak_ptr<int> piw(pi)
use_count()
返回对象的引用计数数量。expired()
弱引用的对象是否存在,当引用计数的数量为 0 时,返回 false。reset()
将指针至为nullptr
lock()
: 返回一个shared_ptr
,同时指向对象的引用计数加1
auto p1 = make_shared<int>(100);
weak_ptr<int> pw(p1);
if (!pw.expired()) {
auto p2 = pw.lock(); // p1 引用计数加 1
if (p2 != nullptr){
// 通过 p2 访问对象
}
// 离开此范围,p1 引用计数减1
}
unique_ptr
同一时间只有一个 unique_ptr
指针指向这个对象,且当指针销毁时,对象也会被释放。
// 方式 1
std::unique_ptr<int> p(new int(100));
// 方式 2
auto p2 = std::make_unique<int>(100)
注意
std::make_unique()
函数是 C++ 14 提供。std::make_unique()
不能使用删除器。
unique_ptr
的操作
- 不支持复制操作。
std::unique_ptr<string> p1(new string("Hello,World!"));
// 以下是错误的
std::unique_ptr<string> p2(p1);
std::unique_ptr<string> p3 = p1;
std::move()
将一个unique_ptr
指针转移到其他unique_ptr
,转移后原指针为nullptr
std::unique_ptr<string> p1(new string("Hello,World!"));
std::unique_ptr<string> p2 = std::move(p1); // 将 p1 指向的对象转移至 p2,同时 p1 指向 nullptr
release()
成员函数:释放对裸指针的控制权,并返回裸指针。返回的裸指针可以使用 delete 控制,也可以用来初始化另一个智能指针。
std::unique_ptr<string> p1(new string("Hello,World!"));
std::unique_ptr<string> p2(p1.release());
// 或者
std::unique_ptr<string> p1(new string("Hello,World!"));
string* str = p1.release()
delete str;
reset()
成员函数- 不代参数,释放指针指向的对象,同时指针指向
nullptr
。 - 代参数,释放指针指向的对象,同时指针指向新的参数。
- 不代参数,释放指针指向的对象,同时指针指向
= nullptr
释放指针指向的对象,同时指针指向nullptr
。get()
成员函数:获取指针指向对象的裸指针。*
解引用,获取指针指向的对象。std::swap()
交换两个指针指向的对象转为
shared_ptr
指针:当unique_ptr
为右值时,可以赋值给shared_ptr
,此时shared_ptr
接管指针指向的对象。
unique_ptr
的删除器
unique_ptr<指向对象类型,删除器> 指针名
typedef void(* fp)(string*); // 函数类型指针
void myDelete(string *pdel) {
delete pdel;
pdel = nullptr;
}
std::unique_ptr<string, fp> p1(new string("Hello,World!"), myDelete);
auto mydella = [](string *pdel) {
delete pdel;
pdel = nullptr;
};
std::unique_ptr<string, decltype(mydella)> p2(new string("Hello,World!"), mydella);
RIME 中的示例
在 RIME 的 src/rime/common.h
中,如下:
template <class T>
using the = std::unique_ptr<T>;
template <class T>
using an = std::shared_ptr<T>;
template <class T>
using weak = std::weak_ptr<T>;
template <class T, class... Args>
inline an<T> New(Args&&... args) {
return std::make_shared<T>(std::forward<Args>(args)...);
}
在 RIME 中 分别使用类型别名:the
表示 unique_ptr
, an
表示 shared_ptr
, weak
表示 weak_ptr
三种智能指针。
使用 New
模板函数构建一个新的 shared_ptr
指针。
std::forward<Args>(args)...
用来将参数转发给 T 的构造函数。
template <class X, class Y>
inline an<X> As(const an<Y>& ptr) {
return std::dynamic_pointer_cast<X>(ptr);
}
template <class X, class Y>
inline bool Is(const an<Y>& ptr) {
return bool(As<X, Y>(ptr));
}
As
用来做 shared_ptr
指针类型转换。其中std::dynamic_pointer_cast<X>(ptr)
被调用来执行动态转换。 std::dynamic_pointer_cast
是一个对 shared_ptr
执行动态转换的函数。如果动态转换成功,则返回一个新类型的 shared_ptr
;如果不成功,则返回 nullptr
。在本例中,它尝试将 shared_ptr
类型的 ptr 转换为 X 类型的 shared_ptr
。
Is
用来判断 shared_ptr
类型 ptr 是否为类型 X。