λ表达式、智能指针

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;  			// 地址 0
    cout << 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_unqie
    unique_ptr<A> p3 = make_unique<A>();  // make_unique 调用构造函数,使用赋值的方式

    // move 转让空间的使用权
    unique_ptr<A> p4(move(p2));
    cout << p2.get() << endl;		// 输出 0
    cout << p4.get() << endl;		// 输出 地址2

    return 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;		// 地址 1
    cout << 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;
}
  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值