lambda 表达式
1、C++11标准支持,实现匿名函数的功能;
2、通常用于实现轻量级的函数
格式
mutable->返回值{函数体}; // 返回值即使是 void 也必须得写
[] 内,可以填外部数据;
() 内,可以带有参数列表。
lambda 表达式的结果,通常使用 auto 获取:
auto p = mutable->返回值{函数体};
等价于:返回值 (*p)(参数列表) = mutable->返回值{函数体};
[]()->返回值{函数体}; // mutable 可省略
[]: 捕获列表,可以捕获所有的外部变量
[a,b]: 按值捕获外部变量 a 和 b,不加 mutable 关键字则不能修改变量
[&a,&b]: 按引用捕获外部变量 a 和 b,即使不加 mutable 也能正常修改变量
[=]: 按值捕获所有的外部变量
[&]: 按引用捕获所有的外部变量
[=,&a]: 按值捕获除了 a 之外的所有外部变量,对 a 进行按引用捕获
[&,a]: 按引用捕获除了 a 外的所有外部变量,对 a 进行按值捕获
使用
// e.g. #include <iostream>
using namespace std;int main()
{int a1 = 90, b1 = 70;double c = 7;// 返回值类型 参数类型auto p = [&a1, b1](int a, int b)mutable->int{a1 = 80;return b;};cout << p(2, 3) << endl;cout << a1 << endl;return 0;
}
💡 练习
使用 lambda 表达式,求两数中的最大值,要求:通过参数传递,不能写复杂的运算。
#include <iostream>
using namespace std;/* ---------- 方法一:---------- */
int main()
{int a = 15;int b = 7;auto p = [ ](int num1, int num2)mutable->int{return num1 > num2 ? num1 : num2;};cout << p(a, b) << endl;return 0;
}/* ---------- 方法二:---------- */
int main()
{int a = 15;int b = 7;auto p = [a, b]()mutable->void{cout << (a > b ? a : b) << endl;};p();return 0;
}
智能指针
堆内存的对象需要手动 delete 销毁,如果忘记使用 delete 销毁就会造成内存泄漏。
所以 C++ 在 ISO 98 标准中引入了智能指针的概念,并在 C++11 中趋于完善。
智能指针是 C++ 中的一种特殊类型,用于管理动态分配的内存。它可以自动释放内存,避免了手动管理内存的繁琐和可能的内存泄漏。需要导入头文件:#include <memory>。
智能指针指向的堆空间,无需手动 delete。
使用智能指针可以让堆内存对象具有栈内存对象的特性,原理是给需要自动回收的堆内存对象套上了一个栈内存的模板对象。
auto_ptr
已经被放弃使用了,但依然可以使用。
(C++98 标准还在使用,后面就弃用了,在复制语义时,会转让空间所有权)
#include <iostream>
#include <memory>
using namespace std;class A
{
public:A() {cout << "A的构造函数" << endl;}~A() {cout << "A的析构函数" << endl;}
};int main()
{A *pnew = new A;// exit(0); // 退出程序,即使使用智能指针也不会释放空间auto_ptr<A> p1(pnew); // 使用原始指针作为参数调用 auto_ptr 的构造函数auto_ptr<A> p2(p1); // p1 把堆空间的所有权,转让给 p2// auto_ptr会在复制指针时,把原来指针对空间的所有权,转让给另一个指针cout << p1.get() << endl; // 智能指针不是一个原始指针,不能直接输出cout << p2.get() << endl; // 要使用 get 函数获取原始指针类型的地址// p2.release(); // 释放 p2 智能指针 对 pnew 的控制权p2.reset(); // 释放控制权且销毁资源对象return 0;
}
unique_ptr(独占指针)
unique_ptr 是一种独占所有权的智能指针,它不能被复制或共享。当 unique_ptr 被销毁时,它所管理的对象也会自动被释放。
#include <iostream>
#include <memory>
using namespace std;class A
{
public:A() {cout << "A的构造函数" << endl;}~A() {cout << "A的析构函数" << endl;}
};int main()
{// 1、使用已有的裸指针 p,初始化 unique_ptr// 可以申请独占指针成功,但是裸指针和独占指针都指向同一片堆空间,// 独占指针失去了对空间的唯一所有权,不建议使用A *p = new A;unique_ptr<A> p1(p);cout << p << endl; // 地址 0cout << p1.get() << endl; // 地址 1,地址1 == 地址0// unique_ptr<A> p2(p1); // 没有拷贝构造函数,不能拷贝// 2、使用 new 关键字,给独占指针申请空间unique_ptr<A> p2(new A);cout << p2.get() << endl; // 地址 2// 3、使用函数,给 unique_ptr 分配空间,C++ 14 支持 make_unqieunique_ptr<A> p3 = make_unique<A>(); // make_unique 调用构造函数,使用赋值的方式// move 转让空间的使用权unique_ptr<A> p4(move(p2));cout << p2.get() << endl; // 输出 0cout << p4.get() << endl; // 输出 地址2return 0;
}
#include <memory>int main() {std::unique_ptr<int> myPtr(new int(10));// 使用 myPtr 操作动态分配的内存// 当 myPtr 超出作用域时,内存会自动释放return 0;
}
shared_ptr(共享指针 / 计数指针)
shared_ptr 是一种带有引用计数的智能指针,多个 shared_ptr 可以共享同一个对象。当没有任何 shared_ptr 指向它时,对象会被销毁。
#include <iostream>
#include <memory>
using namespace std;class A
{
public:A() {cout << "A的构造函数" << endl;}~A() {cout << "A的析构函数" << endl;}
};
int main()
{// 1、通过裸指针,创建共享指针A *p = new A;shared_ptr<A> p1(p);shared_ptr<A> p2(p1);cout << p1.get() << endl; // 地址 1cout << p2.get() << endl; // 地址 2,地址2 == 地址1// 2、通过 new 创建共享指针shared_ptr<A> p3(new A);shared_ptr<A> p4(p3); // p3 和 p4 指向同一片空间shared_ptr<A> p5(p4);cout << p3.get() << endl;cout << p4.get() << endl;cout << p5.get() << endl; // 地址3 == 地址4 == 地址5// 直接让指针值 nullptr,会释放空间所有权// 共享指针引入计数机制 use_count()p4 = nullptr;cout << p5.use_count() << endl;p3 = nullptr;cout << p5.use_count() << endl;p5.reset(); // 成员函数 reset,也可以释放共享指针对空间的所有权cout << p5.use_count() << endl;// 如果 use_count 的个数为0,说明没有指针指向该空间,也会释放掉堆空间cout << p5.use_count() << endl;return 0;
}
#include <memory>int main() {std::shared_ptr<int> ptr1(new int(10));{std::shared_ptr<int> ptr2 = ptr1; // 引用计数加1// 使用 ptr1 和 ptr2 操作动态分配的内存} // ptr2 超出作用域,引用计数减1// 当 ptr1 超出作用域时,内存会自动释放return 0;
}
weak_ptr(协助指针)
weak_ptr 是一种弱引用智能指针,它可以指向 shared_ptr 所管理的对象,但不会改变引用计数。当所有 shared_ptr 都释放后,weak_ptr 会自动失效。
weak_ptr 是一个不控制资源对象的智能指针,也不会影响资源的引用计数,其主要目的协助shared_ptr 工作。
通过 weak_ptr 的构造函数,参数传入一个持有资源对象的 shared_ptr 对象或 weak_ptr 对象即可创建。weak_ptr 与资源对象呈现弱相关性,因此不支持 get 等函数直接操作资源对象。
建议 weak_ptr 调用 lock 函数之前,先检测引用计数是否大于零,或者使用 expired() 函数检测是否可以转为 shared_ptr。
#include <memory>int main() {std::shared_ptr<int> ptr1(new int(10));std::weak_ptr<int> ptr2 = ptr1; // 弱引用{std::shared_ptr<int> ptr3 = ptr2.lock(); // 通过 weak_ptr 获取强引用if (ptr3) {// 使用 ptr3 操作动态分配的内存}} // ptr3 超出作用域,引用计数减1// 当 ptr1 超出作用域时,内存会自动释放return 0;
}