当前位置: 首页 > news >正文

C++11——智能指针和function库

目录

一、智能指针

1. std::unique_ptr(独占所有权指针)

2. std::shared_ptr(共享所有权指针)

3. std::weak_ptr(弱引用指针)

关键区别总结

最佳实践

基本用法

可封装的对象类型

核心特性

示例代码

1. 基本调用

2. 结合 Lambda 和参数传递

3. 作为回调函数

与模板的对比

使用场景

注意事项

总结


一、智能指针

shared_ptr和unique_ptr都支持的操作

shared_ptr<T> sp  空智能指针,可以指向类型为T的对象
unique_ptr<T> up  
p   将p用作一条判断,若p指向一个对象,则为true
*p  解引用p。获得它指向的对象
p->mem 等价于(*p).mem
p.get() 返回p中保存的指针。要小心使用,若智能指针释放了其对象,返回的指针所指向的对象也就消失了
swap(p,q) 交换p和q中的指针
p.swap(q)

share_ptr独有的操作 

make_shared<T>(angs)        返回一个 shared_ptr,指向一个动态分配的类型为了的对象。使用args 初始化此对象
shared_ptr<T> p(q)          p是shared ptrq的拷贝:此操作会递增q中的计数器,g中的指针必须能转换为T*
p=q                         p和q都是shared_ptr,所保存的指针必须能相互转换。此操作会递减p的引用计数,递增q的引用计数;若p的引用计数变为0,则将其管理的原内存释放
p.unique()
p.use_count()                若p.use_count()为1,返true:否则返回false返回与p共享对象的智能指针数量;可能很慢,主要用于调试(参见4112节,第143页

 

 

1. std::unique_ptr(独占所有权指针)

  • 特点

    • 独占资源的所有权,同一时间只能有一个 unique_ptr 指向某个对象。

    • 不能拷贝构造或赋值,但可以通过 std::move 转移所有权。

    • 生命周期结束时(超出作用域或被重置),自动释放管理的资源。

  • 适用场景

    • 管理动态分配的资源,明确所有权单一的情况。

    • 替代 C++98 的 auto_ptr(已弃用)。

  • 示例

    #include <memory>void example_unique_ptr() {std::unique_ptr<int> ptr1(new int(42));  // 创建 unique_ptrstd::unique_ptr<int> ptr2 = std::move(ptr1); // 转移所有权if (ptr1) {// ptr1 不再拥有资源,不会执行此处}if (ptr2) {*ptr2 = 10; // 修改指向的值}
    } // 自动释放 ptr2 的资源


2. std::shared_ptr(共享所有权指针)

  • 特点

    • 通过引用计数(reference counting)管理资源,允许多个 shared_ptr 共享同一对象。

    • 当最后一个 shared_ptr 被销毁或重置时,资源被释放。

    • 可以通过 std::make_shared 高效创建(减少内存分配次数)。

  • 适用场景

    • 需要多个指针共享同一资源的场景。

    • 需要传递资源所有权但不确定何时释放的情况。

  • 示例

    #include <memory>void example_shared_ptr() {std::shared_ptr<int> ptr1 = std::make_shared<int>(42); // 推荐使用 make_sharedstd::shared_ptr<int> ptr2 = ptr1; // 引用计数 +1std::cout << ptr1.use_count() << std::endl; // 输出 2
    } // ptr1 和 ptr2 销毁,引用计数归零,资源释放


3. std::weak_ptr(弱引用指针)

  • 特点

    • 指向 shared_ptr 管理的资源,但不增加引用计数。

    • 用于解决 shared_ptr 的循环引用问题(如两个对象相互持有对方的 shared_ptr)。

    • 需要通过 lock() 方法获取临时的 shared_ptr 来访问资源。

  • 适用场景

    • 需要观察 shared_ptr 资源但不影响其生命周期。

    • 打破循环引用。

  • 示例

    #include <memory>void example_weak_ptr() {std::shared_ptr<int> shared = std::make_shared<int>(42);std::weak_ptr<int> weak = shared;if (auto temp = weak.lock()) { // 转换为 shared_ptrstd::cout << *temp << std::endl; // 输出 42}shared.reset(); // 释放资源if (weak.expired()) { // 检查资源是否已被释放std::cout << "Resource is gone." << std::endl;}
    }


关键区别总结

智能指针所有权拷贝/赋值性能开销适用场景
unique_ptr独占只能移动单一所有权,明确生命周期
shared_ptr共享允许拷贝引用计数共享所有权,不确定生命周期
weak_ptr无(仅观察)允许拷贝无计数解决循环引用,观察资源

最佳实践

  1. 优先使用 unique_ptr:默认情况下使用 unique_ptr,仅在需要共享时使用 shared_ptr

  2. 避免裸指针与智能指针混用:不要将智能指针管理的资源通过裸指针传递。

  3. 使用 make_shared 和 make_unique(C++14+):

    cpp

    复制

    auto ptr = std::make_unique<int>(42);  // C++14 支持
    auto ptr2 = std::make_shared<int>(42); // 减少内存分配次数
  4. 注意循环引用:如果两个对象互相持有 shared_ptr,使用 weak_ptr 打破循环。


基本用法

  • 头文件

    #include <functional>

  • 定义

    std::function<返回值类型(参数类型列表)> func;

    例如:

    std::function<int(int, int)> func; // 封装一个接受两个 int、返回 int 的可调用对象


可封装的对象类型

std::function 可以封装以下类型的可调用对象:

  1. 普通函数

    int add(int a, int b) { return a + b; }
    std::function<int(int, int)> func = add;

  2. Lambda 表达式

    std::function<int(int, int)> func = [](int a, int b) { return a * b; };

  3. 函数对象(仿函数)

    struct Multiply {int operator()(int a, int b) { return a * b; }
    };
    Multiply mul;
    std::function<int(int, int)> func = mul;

  4. 类的成员函数(需结合 std::bind):

    class Calculator {
    public:int subtract(int a, int b) { return a - b; }
    };Calculator calc;
    auto bound_func = std::bind(&Calculator::subtract, &calc, std::placeholders::_1, std::placeholders::_2);
    std::function<int(int, int)> func = bound_func;

  5. 静态成员函数(直接赋值):

    class Math {
    public:static int divide(int a, int b) { return a / b; }
    };
    std::function<int(int, int)> func = Math::divide;


核心特性

  1. 类型擦除

    • std::function 隐藏了底层可调用对象的具体类型,通过统一的接口调用。

    • 例如,无论是 Lambda 还是函数指针,都可以被同一个 std::function 类型包装。

  2. 运行时多态

    • 可以在运行时动态绑定不同的函数或对象,适用于回调机制和事件驱动编程。

  3. 空状态检查

    • 默认初始化的 std::function 为空,调用空 function 会抛出 std::bad_function_call 异常。

    • 使用 operator bool() 检查是否可调用:

      if (func) {func(2, 3); // 安全调用
      }


示例代码

1. 基本调用
#include <iostream>
#include <functional>void hello() {std::cout << "Hello, World!" << std::endl;
}int main() {std::function<void()> func = hello;func(); // 输出 "Hello, World!"return 0;
}
2. 结合 Lambda 和参数传递
#include <functional>int main() {std::function<int(int, int)> operation;// 动态绑定加法operation = [](int a, int b) { return a + b; };std::cout << operation(3, 4) << std::endl; // 输出 7// 动态绑定乘法operation = [](int a, int b) { return a * b; };std::cout << operation(3, 4) << std::endl; // 输出 12return 0;
}
3. 作为回调函数
#include <functional>
#include <vector>class Button {
public:using Callback = std::function<void()>;void setOnClick(Callback callback) {onClick = callback;}void click() {if (onClick) onClick();}private:Callback onClick;
};int main() {Button btn;btn.setOnClick([]() { std::cout << "Button clicked!" << std::endl; });btn.click(); // 输出 "Button clicked!"return 0;
}

与模板的对比

  • 模板:在编译时确定类型,性能更高,但无法动态更换函数类型。

  • std::function:运行时动态绑定,灵活性更高,但有轻微性能开销(类型擦除和虚函数调用)。


使用场景

  1. 回调机制(如 GUI 事件处理、网络请求完成回调)。

  2. 策略模式:动态切换算法或行为。

  3. 函数注册表:将不同函数存储在容器中统一调用。

  4. 延迟执行:将函数绑定到某个条件触发时执行。


注意事项

  1. 性能std::function 的调用比直接调用函数或模板稍慢(涉及间接调用),但对大多数场景影响不大。

  2. 内存分配:若封装的函数对象较大(如捕获大量变量的 Lambda),std::function 可能触发堆内存分配。

  3. 绑定成员函数:必须结合 std::bind 或 Lambda 表达式,并传递对象实例的指针或引用。


总结

std::function 是 C++11 中实现类型安全的函数抽象的核心工具,它通过统一的接口封装任意可调用对象,极大提升了代码的灵活性和可维护性。合理使用 std::function 可以简化回调设计,实现动态行为绑定,但需注意其性能和使用场景的平衡。

相关文章:

C++11——智能指针和function库

目录 一、智能指针 1. std::unique_ptr&#xff08;独占所有权指针&#xff09; 2. std::shared_ptr&#xff08;共享所有权指针&#xff09; 3. std::weak_ptr&#xff08;弱引用指针&#xff09; 关键区别总结 最佳实践 基本用法 可封装的对象类型 核心特性 示例代码…...

[操作系统] 文件的软链接和硬链接

文章目录 引言硬链接&#xff08;Hard Link&#xff09;什么是硬链接&#xff1f;硬链接的特性硬链接的用途 软链接&#xff08;Symbolic Link&#xff09;什么是软链接&#xff1f;软链接的特性软链接的用途 软硬链接对比文件的时间戳实际应用示例使用硬链接节省备份空间用软链…...

RabbitMQ面试题及原理

RabbitMQ使用场景&#xff1a; 异步发送&#xff08;验证码、短信、邮件…&#xff09;MYSQL和Redis, ES之间的数据同步分布式事务削峰填谷 1. 消息可靠性&#xff08;不丢失&#xff09; 消息丢失场景&#xff1a; RabbitMQ-如何保证消息不丟失&#xff1f; 开启生产者确…...

SpringBoot中Get请求和POST请求接收参数详解

1、Get请求 1.1 方法形参接收参数 这种方式一般适用参数比较少的情况&#xff0c;并且前后端参数名称必须保持一致 RestController RequestMapping(“/user”) Slf4j public class DemoController { GetMapping("/query") public void getStudent(String name,Strin…...

分布式日志和责任链路

目录 日志问题 责任链问题 分布式日志 GrayLog简介 部署安装 收集日志 配置Inputs 集成微服务 日志回收策略 搜索语法 搜索语法 自定义展示字段 日志统计仪表盘 创建仪表盘 链路追踪 APM 什么是APM 原理 技术选型 Skywalking简介 部署安装 微服务探针 整合…...

h5 IOS端渐变的兼容问题 渐变实现弧形效果

IOS端使用渐变的时候有兼容问题 以下是问题效果&#xff0c;图中黑色部分期望的效果应该是白色的。但是ios端是下面的样子…… 安卓pc 支持&#xff1a; background-image: radial-gradient(circle 40rpx at 100% 0, #f3630c 40rpx, rgb(255, 255, 255) 50%);安卓pc ios支持…...

哈希算法--猜数字游戏

1.题目要求 输入两个位数相同的数&#xff0c;判断对应位置的数字是否相等&#xff0c;返回两个数。第一个数是数字和位置完全猜对的数字个数&#xff0c;第二个数是数字大小猜对但位置不对的数字个数 2.逐步编程 2.1 定义函数 def g(secret,guess):sec_dic{}gue_dic{}# 定义…...

idea生成自定义Maven原型(archetype)项目工程模板

一、什么是Maven原型&#xff08;Maven archetype&#xff09; 引自官网的介绍如下&#xff1a; Maven原型插件官网地址 这里采用DeepSeek助手翻译如下&#xff1a; Maven 原型 什么是原型&#xff1f; 简而言之&#xff0c;原型是一个 Maven 项目模板工具包。原型被定义为一…...

Redis面试常见问题——使用场景问题

目录 Redis面试常见问题 如果发生了缓存穿透、击穿、雪崩&#xff0c;该如何解决&#xff1f; 缓存穿透 什么是布隆过滤器&#xff1f; 缓存击穿 缓存雪崩 双写一致性&#xff08;redis做为缓存&#xff0c;mysql的数据如何与redis进行同步呢&#xff1f;&#xff09; …...

样式和ui(待更新)

element-plus 先在项目下执行安装语句执行按需导入的命令按照官方文档修改vitest.json sass样式定制 npm -i sass -D在项目下准备定制的样式文件 styles/element/index.scss(!注意这里是.scss文件在vitest.json 修改配置文件 Components({resolvers: [ElementPlusResolver(…...

大摩闭门会:250228 学习总结报告

如果图片分辨率不足&#xff0c;可右键图片在新标签打开图片或者下载末尾源文件进行查看 本文只是针对视频做相应学术记录&#xff0c;进行学习讨论使用...

线程(Thread)

一、概念 线程&#xff1a;线程是一个轻量级的进程 二、线程的创建 1、线程的空间 &#xff08;1&#xff09;进程的空间包括&#xff1a;系统数据段、数据段、文本段 &#xff08;2&#xff09; 线程位于进程空间内部 &#xff08;3&#xff09; 栈区独享、与进程共享文本段、…...

AI军备竞赛2025:GPT-4.5的“情商革命”、文心4.5的开源突围与Trae的代码革命

AI军备竞赛2025&#xff1a;GPT-4.5的“情商革命”、文心4.5的开源突围与Trae的代码革命 ——一场重塑人类认知边界的技术战争 一、OpenAI的“感性觉醒”&#xff1a;GPT-4.5的颠覆与争议 1.1 从“冷面学霸”到“温柔导师”&#xff1a;AI的情商跃迁 当用户输入“朋友放鸽子&…...

DeepSeek + 自由职业 发现新大陆,从 0 到 1 全流程跑通商业 IP

DeepSeek 自由职业 发现新大陆&#xff0c;从 0 到 1 全流程跑通商业 IP 商业定位1. 商业定位分析提示词2. 私域引流策略提示词3. 变现模型计算器提示词4. 对标账号分析提示词5. 商业IP人设打造提示词6. 内容选题策略提示词7. 用户人群链分析提示词8. 内容布局与转化路径设计提…...

Java进阶——常用工具类

日常开发中&#xff0c;Arrays、Collections 和 Objects 是非常实用的工具类&#xff0c;提供了丰富的功能&#xff0c;从而可以更高效地处理数组、集合和对象。本文将详细介绍这三个工具类的重要知识细节。 本文目录 一、 Arrays数组转集合并行排序优化Stream 支持 二、 Colle…...

【考试大纲】高级系统架构设计师考试大纲

目录 引言一、 考试说明1.考试目标2.考试要求3.考试科目设置二、 考试范围考试科目1:系统架构设计综合知识考试科目2:系统架构设计案例分析考试科目3:系统架构设计论文引言 最新的系统架构设计师考试大纲出版于 2022 年 11 月,本考试大纲基于此版本整理。 一、 考试说明…...

上位机知识篇---四种CPU架构交叉编译

文章目录 前言一、四种 CPU 架构1. x86/x86_64指令集位宽&#xff1a;应用场景编译工具 2. ARM指令集位宽&#xff1a;应用场景编译工具 3. MIPS指令集位宽应用场景编译工具 4. RISC-V指令集位宽应用场景编译工具 二、交叉编译1. 什么是交叉编译&#xff1f;定义应用场景 2. 交…...

隐式转换为什么导致索引失效

SELECT * FROM users WHERE id 123;这条语句失效的原因就是id是int类型的主键&#xff0c;比较的时候把id从int转化为字符串来比较了&#xff0c;而字符串的比较规则和int的比较规则明显不同&#xff0c;字符串是字典序比较的&#xff0c;还涉及到数据的长度&#xff0c;那为什…...

【含文档+PPT+源码】基于过滤协同算法的旅游推荐管理系统设计与实现

项目介绍 本课程演示的是一款基于过滤协同算法的旅游推荐管理系统设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套…...

SpringBoot @Value 注解使用

Value 注解用于将配置文件中的属性值注入到Spring管理的Bean中。 1. 基本用法 Value 可以直接注入配置文件中的属性值。 配置文件 (application.properties 或 application.yml) 配置文件定义需要注入的数据。 consumer:username: lisiage: 23hobby: sing,read,sleepsubje…...

超越YOLO:在RGBT-Tiny上,为什么DETR和Diffusion模型对小目标检测更有效?

超越YOLO&#xff1a;DETR与Diffusion模型在小目标检测中的技术突破 深夜的海上搜救任务中&#xff0c;热成像画面里几个像素大小的落水者身影若隐若现&#xff1b;城市高空无人机巡检时&#xff0c;监控画面中88像素的违规车辆几乎与背景融为一体。这些真实场景揭示了计算机视…...

当企业拥有了创新的 “上帝视角”,会发生什么?

当企业拥有了创新的 “上帝视角”&#xff0c;会发生什么&#xff1f;&#xff0d;&#xff0d;研企配 AI 大数据&#xff0c;打开中国企业产业洞察的上帝之窗在商业史上&#xff0c;所有的溃败都始于认知的闭环。14年前&#xff0c;诺基亚CEO约玛奥利拉在手机业务售出的发布会…...

车ECU安全刷写(Secure Flashing/Programming)

车 ECU 安全刷写&#xff0c;核心是UDS 协议 安全访问 双分区回滚 供电 / 校验 / 合规全闭环。一、核心基础1. 定义与目标ECU 安全刷写&#xff1a;通过 OBD/CAN/Ethernet&#xff0c;按 ISO14229&#xff08;UDS&#xff09;、ISO15765 标准&#xff0c;对发动机 / 变速箱 …...

Epigenase m6A 甲基化酶活性/抑制比色法检测试剂盒:快速、灵敏、高通量适配

一、产品概述Epigenase m6A 甲基化酶活性/抑制比色法检测试剂盒&#xff0c;由Cytoskeleton推出&#xff0c;艾美捷代理&#xff0c;它是一套完整的优化缓冲液与试剂组合&#xff0c;专用于定量检测总 m6A 甲基化酶&#xff08;甲基转移酶&#xff09;的活性或抑制效果。该试剂…...

矢量网络分析仪在MRI射频子系统研发测试中的应用

磁共振成像&#xff08;MRI&#xff09;正经历双向演进&#xff1a;一方面&#xff0c;高场强系统向7T及更高场强发展&#xff0c;持续推动成像分辨率提升&#xff1b;另一方面&#xff0c;低场强永磁体技术逐步成熟&#xff0c;使便携式MRI在急救室、ICU及基层医疗场景中的应用…...

OpenClaw学习助手:Qwen3.5-9B-AWQ-4bit自动整理网课截图笔记

OpenClaw学习助手&#xff1a;Qwen3.5-9B-AWQ-4bit自动整理网课截图笔记 1. 为什么需要自动化学习助手 作为一名经常通过网课充电的技术从业者&#xff0c;我长期被一个痛点困扰&#xff1a;每次听完两小时的课程&#xff0c;手机相册里会堆满几十张截图&#xff0c;里面有老…...

DAY4--SQL限制返回行数查询

SQL基础入门&#xff1a;电商用户数据限制返回行数查询实操 这一章能解决什么电商工作问题&#xff1f; 这一章要学的LIMIT&#xff0c;是我认为电商数据分析新人最应该刻进肌肉记忆的语法。因为它直接关系到两件事&#xff1a;你的工作效率&#xff0c;以及你的职场安全。 我先…...

HC32F460引脚复用避坑指南:如何正确释放SWDIO/SWCLK做普通IO

HC32F460引脚复用实战&#xff1a;释放SWDIO/SWCLK的完整解决方案 当你在华大HC32F460项目中发现GPIO资源紧张时&#xff0c;PB3/PB4这些复用引脚就像藏在抽屉里的备用钥匙。但当你真正需要使用它们时&#xff0c;却发现这些引脚被调试接口牢牢占据。这不是简单的配置问题&…...

Windows下OpenClaw安装详解:对接Kimi-VL-A3B-Thinking图文模型

Windows下OpenClaw安装详解&#xff1a;对接Kimi-VL-A3B-Thinking图文模型 1. 为什么选择OpenClaw与Kimi-VL-A3B-Thinking组合 去年我在处理大量图文资料归档时&#xff0c;发现手动整理效率极低。直到尝试将OpenClaw与Kimi-VL-A3B-Thinking模型对接后&#xff0c;才真正实现…...

大以论文与万方、维普、WPS AI 综合对比(2026)

毕业季论文格式问题频发&#xff0c;手动排版耗时、通用模板不匹配、公式图表易错乱是常态。万方、维普以查重为主&#xff0c;WPS AI 偏向通用办公&#xff0c;而大以论文作为7 年专注毕业论文排版的老牌工具&#xff0c;在专业性、稳定性与院校适配性上更具优势。一、核心对比…...