C++开发基础——智能指针

【C++】————智能指针 在C++中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存。c++中用的最多的是下面三种智能指针。 阅读详情

一,智能指针

1.智能指针简介

智能指针是用法和行为类似于指针的类对象。

智能指针的底层对原始指针做了一定的封装。

智能指针除了像指针一样可以存储变量的地址,还提供了其他功能,比如可以管理动态内存分配,对引用进行计数等。

当智能指针所指向的变量离开了作用域或被重置时,智能指针会自动释放该变量所占用的堆内存资源。

至于为什么要引入智能指针,可以参考下面这段代码:

void func_1()
{
       Sample* obj_one = new Sample();
       if(something_wrong())
              throw exception();
       delete obj_one;
}

每次调用该函数的时候,都需要在堆中申请一段内存,然后在函数的最后释放该内存。但是当函数运行期间出现异常的时候,delete将不被执行,此时申请到的内存得不到释放,会发生内存泄露。智能指针由于是类对象,该类对象可以在析构的时候自动释放智能指针所指向的内存。因此,如果此时使用智能指针代替原始指针,可以不用手动调用"delete/delete []",智能指针指向的堆内存会自动被释放。

上述代码可以改写为:

void func_2()
{
       auto obj_two = make_unique<Sample>();
       if(something_wrong())
              throw exception();
}

当unique_ptr实例离开作用域时(代码执行到了函数末尾,或者函数抛出异常),就会在其析构函数中自动释放obj_two对象所占有的内存资源。

标准库中提供了相应的类模板,它们可以将任何数据类型封装成智能指针,使用它们时,需要引入<memory>头文件。

智能指针常用的类模板有:

std::unique_ptr<T>

std::shared_ptr<T>

std::weak_ptr<T>

由上述的类模板可以生成三种类型的智能指针实例。这三种智能指针实例的区别在于,管理原始指针的方式不一样。

shared_ptr允许多个指针指向同一个变量。

unique_ptr则独占所指向的变量。

weak_ptr则指向shared_ptr所管理的变量。

2.智能指针的基础用法

1.智能指针的初始化

智能指针是基于类模板生成的,因此,要初始化一个智能指针,就必须声明指针所指向的数据类型,不然智能指针里面包含的原始指针是个空指针。

初始化方式一,在智能指针构造函数中new一个新对象。

struct C{
    int a;
    int b;
};
std::shared_ptr<C> p1(new C);
std::unique_ptr<int> p2(new int(40));

初始化方式二,采用make_shared函数(C++11标准)、make_unique函数(C++14标准)。

std::shared_ptr<int> p3 = std::make_shared<int>(15);
std::unique_ptr<int> p4 = std::make_unique<int>(10);

智能指针在初始化时,还可以用于指向动态分配的数组。

代码样例,创建长度为10的整型数组:

//方式一
auto Array_1 = make_unique<int[]>(10);
//方式二
std::unique_ptr<int[]> Array_2(new int[10]);
//类型+[],表示初始化指向数组的智能指针
//后面的具体用法和数组类似
Array_1[0] = 1;
Array_2[0] = 2;

注意,初始化weak_ptr需要用到shared_ptr。

代码样例:

auto sh_p = make_shared<int>(40);
weak_ptr<int> wp1(sh_p);
weak_ptr<int> wp2 = sh_p;
2.智能指针的解引用

智能指针的解引用操作与原始指针类似,可以调用"*"或"->"对智能指针进行解引用,访问分配到的堆内存地址。

但是weak_ptr不提供指针的解引用操作,即无法调用"*"或"->"获得weak_ptr所指向的变量。

完整C++代码实现:

#include <iostream>
#include <memory>
int main() {
    struct C {
        int a=1;
        int b=2;
    };
    std::shared_ptr<C> p1(new C);
    std::unique_ptr<int> p2(new int(40));
    std::shared_ptr<int> p3 = std::make_shared<int>(15);
    std::unique_ptr<int> p4 = std::make_unique<int>(10);
    std::weak_ptr<int> p5 = p3;
    std::cout << p1->a << std::endl;
    std::cout << p1->b << std::endl;
    std::cout << *p2 << std::endl;
    std::cout << *p3 << std::endl;
    std::cout << *p4 << std::endl;
    std::cout << *p5.lock() << std::endl;
    return 0;
}

运行结果:

1
2
40
15
10
15

3.unique_ptr智能指针

常用的成员函数:

get(): 返回指向变量的原始指针。

reset(): 重置智能指针,使它所持有的资源为空。

swap(): 交换两个智能指针所管理的资源。

release(): 返回指向变量的原始指针,并释放所有权。

用法说明:

reset()让unique_ptr重新指向给定的指针。如果unique_ptr不为空,它原先占有的内存资源将被释放。

由于一个初始化后的unique_ptr独占了它所指向的变量,因此unique_ptr不支持普通的拷贝或赋值操作。

虽然不能拷贝或赋值unique_ptr,但可以通过调用release()/reset()函数将指针的所有权转移给另一个unique_ptr。

4.shared_ptr智能指针

常用的成员函数:

get(): 返回指向变量的原始指针。

reset(): 重置智能指针,使它所持有的资源为空。

swap(): 交换两个智能指针所管理的资源。

use_count(): 返回智能指针所指向变量的被引用数量。

unique(): 检查所指向的变量是否仅由当前shared_ptr的实例管理。

用法说明:

shared_ptr允许多个指针指向同一块堆内存。

shared_ptr提供了引用计数,监视当前变量正在被多少个指针实例所引用。

由于shared_ptr存在引用计数,仅在最后一个引用被销毁或重置时,该智能指针才会释放持有的内存资源。。

shared_ptr可被以下函数强制转换:

const_pointer_cast()

dynamic_pointer_cast()

static_pointer_cast()

reinterpret_pointer_cast() (C++17标准引入)

如图所示,指针p1、p2指向同一块内存地址。

5.weak_ptr智能指针

常用的成员函数:

reset(): 重置智能指针,使它所持有的资源为空。

swap(): 交换两个智能指针所管理的资源。

expired(): 检查weak_ptr所指向的资源是否有效,返回true的时候,垃圾回收进程就会清除该指针所指向的内存资源。

use_count(): 返回智能指针所指向shared_ptr的数量。

lock(): 获取weak_ptr所指向的shared_ptr实例。

用法说明:

weak_ptr不占有内存资源,但是可以指向由shared_ptr管理的内存资源。

当weak_ptr指向shared_ptr时,是弱共享shared_ptr,并不会使shared_ptr的引用计数增加。

weak_ptr的出现可以帮助开发者解决智能指针使用期间发生的"循环引用"问题。

完整C++代码实现:

#include <iostream>
#include <memory>
using namespace std;

void Check(weak_ptr<int>& wp) {
    shared_ptr<int> sp = wp.lock(); //获得shared_ptr<int>实例
    if (sp != nullptr)
        cout << "still " << *sp << endl;
    else
        cout << "pointer is invalid." << endl;
}

int main() {
    shared_ptr<int> sp1(new int(40));
    shared_ptr<int> sp2 = sp1;
    weak_ptr<int> wp = sp1; //wp指向shared_ptr<int>实例
    cout << *sp1 << endl;
    cout << *sp2 << endl;
    cout << sp1.use_count() << endl;
    cout << sp2.use_count() << endl;
    Check(wp);
    sp1.reset();
    /*
    cout << sp1 << endl;  
    返回:00000000
    */
    cout << *sp2 << endl;
    cout << sp1.use_count() << endl;
    cout << sp2.use_count() << endl;
    cout << sp2.unique() << endl;
    Check(wp);
    sp2.reset();
    cout << sp2.use_count() << endl;
    Check(wp);
    return 0;
}

运行结果:

40
40
2
2
still 40
40
0
1
1
still 40
0
pointer is invalid.

6.智能指针的复制和移动

unique_ptr不支持复制、赋值等操作,它只能被移动,而移动操作经常借助std::move函数来实现。

std::move可以把一个智能指针所占有的资源转移给另一个智能指针。

shared_ptr包含一个显式的构造函数,可用于将右值unique_ptr转换为shared_ptr。转换成功以后,shared_ptr将接管unique_ptr所占有的所有资源。因此,如果unique_ptr为右值(可以粗略理解为,位于赋值符号的右边)的时候,可以将其赋值给shared_ptr。

复制操作会让shared_ptr所指向变量的引用计数加1,而移动操作不会让shared_ptr所指向变量的引用计数加1。

1.unique_ptr转shared_ptr代码样例:

std::shared_ptr<int> p1 = std::make_unique<int>(66);

完整C++代码实现:

#include <iostream>
#include <memory>
int main() {
    std::shared_ptr<int> p1 = std::make_unique<int>(66);
    std::cout << *p1 << std::endl;
    std::cout << p1.use_count() << std::endl;
    return 0;
}

运行结果:

66
1

2.移动操作代码样例:

//p1指向该int对象
shared_ptr<int> p1(new int(40));

//移动构造p2
//p1指向的内存为空,p2指向该int对象
shared_ptr<int> p2(std::move(p1));

//p2指向的内存为空,p3指向该int对象
shared_ptr<int> p3;
p3 = std::move(p2);

//整个过程中,int对象的引用计数保持在1

完整C++代码实现:

#include <iostream>
#include <memory>
int main() {
    std::shared_ptr<int> p1(new int(40));
    std::shared_ptr<int> p2(std::move(p1));
    std::shared_ptr<int> p3;
    p3 = std::move(p2);
    std::cout << p3.use_count() << std::endl;
    std::shared_ptr<int> p4;
    std::shared_ptr<int> p5;
    p4 = p3;
    p5 = p3;
    std::cout << p3.use_count() << std::endl;
    p3.reset();
    p3 = std::make_unique<int>(10);
    std::cout << p3.use_count() << std::endl;
    return 0;
}

运行结果:

1
3
1

7.关于new/delete的补充说明

显式地调用new和delete不仅会增加代码的复杂度,还会引发内存泄露等风险。

如果必须要使用new/delete,可以考虑以下措施来避免:

1.尽可能使用栈内存

栈内存不会造成内存泄露,且资源一旦超出栈的使用范围就会被销毁。

2.使用make functions在堆上分配资源

例如,使用std::make_unique<T>或std::make_shared<T>来实例化资源,然后将它包装成一个资源管理对象去管理资源以及智能指针。

3.尽量使用容器(标准库中的容器,Boost中的容器等)

容器会对其元素进行存储空间的管理,这些官方容器都实现了自己的内存管理逻辑,避免内存出问题。

至于为何要采用上述规则,后面会新增动态内存分配和右值引用等相关章节来详细说明。

二,参考阅读

《C++ Primer》

《C++代码整洁之道》

《C++高级编程》

《C++新经典》

https://www.apiref.com/cpp-zh/cpp/memory.html

https://learn.microsoft.com/zh-cn/cpp/cpp/smart-pointers-modern-cpp?view=msvc-170

【C++学习成长的四个层次 cpp】-- 从零基础到高级开发者的必经之路 【C++学习成长的四个层次 cpp】-- 从零基础到高级开发者的必经之路C++作为一门强类型的编程语言,拥有广泛的应用领域,其中包括游戏、科学计算、操作系统等等。如果你想要成为一名优秀的C++开发者,那么你需要掌握C++的核心概念,熟练使用C++的常用库和工具,并且了解C++的内部机制。在这篇文章中,我们将介绍C++学习成长的四个层次,帮助你系统地掌握C++这门编程语言。 阅读详情

相关推荐

实现带引用计数的C++智能指针

引用计数是一种资源管理技术,用于跟踪资源被引用的次数。在智能指针的上下文中,每个资源对象都与一个计数器相关联。每当有一个新的引用指向该对象时,计数器就会增加;而当引用被销毁或不再指向该对象时,计数器就会减少。当计数器的值减少到零时,说明没有更多的引用指向该对象,资源就可以被安全地释放。这种方法简化了资源管理,因为程序员不需要手动调用释放函数,而是在对象生命周期的末尾,由引用计数机制自动进行清理。SharedPtr模板类允许SharedPtr。

weixin_42591413的博客 894

智能指针

一、简介 动态内存:除了静态内存和栈内存,每个程序还拥有一个内存池。这部分内存被称作自由空间(free store)或堆(heap)。程序用堆来存储动态分配(dynamicallyallocate)的对象——即那些在程序运行时分配的对象。动态对象的生存期由程序来控制,也就是说,当动态对象不再使用时,我们的代码必须显式地销毁它们。 虽然使用动态内存有时是必要的,但正确地管理动态内存是非常棘手的。 **智能指针存在的原因:**动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极其困难的。有时我们会忘记释

季风的博客 634

矿卡CMP 170HX的AI推理性能优化实战

GPU计算在现代AI推理中扮演着核心角色,其并行计算架构特别适合处理神经网络的大规模矩阵运算。通过CUDA指令集优化和计算管线重构,可以显著提升硬件利用率,这在边缘计算和带宽敏感型任务中尤为重要。以NVIDIA CMP 170HX矿卡为例,通过禁用FMA指令和框架适配优化,其FP32性能可提升15.9倍,在Qwen2.5-1.5B模型的4-bit量化推理中达到A100同架构78%的解码速度。这种优化技术不仅让淘汰矿卡重获新生,更为边缘AI部署提供了高性价比解决方案,特别适合7B以下量化模型部署和多路视频分析

weixin_30432579的博客 630

19.智能指针

智能指针

SQZXR的博客 663

(南京观海微电子)——GH700X调试指南--SPI 接口+LVDS-测试盒使用方法

1表示OTP完成后,读取烧录值是否一致来判断是否烧录成功,2表示同时检测VCOM是否一致以及烧录次数是否增加,3表示不做任何检测,由用于自行在程序中判断。[格式]:SetFindVcomEn (<开启或关闭>),ON表示开启VCOM搜寻,默认是开启的,只要使能OTP烧录,按OTP按键则进行VCOM查询;[功能]:OTP完成检测类别,用于设置OTP完成后检测OTP次数还是OTP值来判断OTP是否成功。[功能]:用于设置VCOM查询使能,比如需要烧全代码而不需要对VCOM查询时,可以禁止VCOM查询。

m0_75095200的博客 1666

R语言分类变量的统计描述

三篇介绍了连续变量的统计描述的R语言相关函数,计算数值的相关统计指标。本文介绍分类变量的统计描述及如何在R语言中实现。 不同于连续变量,分类变量的统计描述主要是汇总分类变量各类别例数及百分比。 1、table()函数 ...

zsc943290710的博客 1万+

C++智能指针auto_ptr、unique_ptr、shared_ptr、weak_prt详解

C++智能指针auto_ptr、unique_ptr、shared_ptr、weak_prt详解

GodFishhh的博客 2468

行人重识别技术(Re-ID)概述、研究现状以及相关数据集下载

ReID技术概述什么是ReID一般流程Re-ID特点研究现状难点数据集reid常用数据集以及下载链接评价指标实现思路研究方式基于表征学习基于度量学习基于局部特征全局特征切片姿态基于视频序列RQEN基于GANCamStyleDG-NetGAN总结对比未来方向建议文献 什么是ReID 行人重识别是指利用计算机视觉技术,判断在不同时间段、不同监控下出现的行人图像是否属于同一人员的技术。行人重识别是最近几年在视频分析领域下热门的研究领域,可以看做是人脸识别应用的拓展。现在大街上的监控较多,由于设备质量、成像光线、.

留缘的博客 1万+

C++ 深入智能指针

学习记录

学习记录 1620

ubuntu安装eigen3.3.7

查看已安装版本: gedit /usr/include/eigen3/Eigen/src/Core/util/Macros.h 或 gedit /usr/local/include/eigen3/Eigen/src/Core/util/Macros.h 卸载先前版本: sudo updatedb locate eigen3 得到eigen库的位置 卸载: sudo rm -rf /usr/include/eigen3 /usr/lib/cmake/eigen3 ...

reason的博客 1万+

记住这两个纯净版Windows11各系列版本系统下载网站

记住这两个纯净版Windows11各系列版本系统下载网站 HelloWindows是一个完整极致的Windows纯净系统下载站,不夹带任何私货,系统全部来源于微软官方原版,本站只是收录官方发布的系统以及工具,方便大家下载,请放心使用。永久在线:www.hellowindows.cn。HelloWindows.cn - 精校 完整 极致 Windows系统下载仓储站。

拥抱具身智能,昇腾Ascend C 7014

【C++】智能指针

【C++】智能指针

lyk82698的博客 806

车间数据孤岛终于破了!C#上位机+MQTT打通产线与MES,数据延迟从小时级降到秒级

本文针对工业上位机开发中常见的车间数据与企业管理系统(MES)割裂问题,提出基于C#和MQTT协议的完整解决方案。通过EMQX MQTT Broker实现数据实时双向传输,将质量追溯时间从2小时缩短至10秒,生产计划自动下发,实现秒级数据延迟。方案采用分层解耦架构,支持设备更换和系统升级,核心优势包括低延迟、高可靠性和易扩展性。文章详细介绍了MQTT协议选型理由、整体架构设计、技术选型(EMQX Broker和MqttNet客户端),并提供了C#实现代码和部署流程。该方案已在实际产线验证,可有效解决&quo

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 480

C++开发基础之智能指针(smart pointers)

C++ 智能指针(smart pointers)是一种可以自动管理内存的指针。在 C++ 中,手动管理内存很容易出错,特别是在涉及到动态分配内存和释放内存的时候。使用智能指针可以避免很多内存操作上的错误,提高代码的可读性和安全性。智能指针有三种常用的类型:shared_ptr 、 unique_ptr和weak_ptr。下面将介绍它们的用法。

dotnet研习社 1608

Open3D 体素下采样【2026最新版】

体素滤波,博客长期更新,本文最近更新时间为:2026年4月11日。

点云侠的博客 37万+

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

UE5 C++进阶:从UObject到智能指针,掌握核心基础设施与模块化开发

在游戏开发中,内存管理与对象生命周期是构建稳定系统的基石。通过垃圾回收机制与智能指针,开发者可以避免内存泄漏与悬垂指针问题,确保资源高效释放。反射系统则实现了代码与编辑器的无缝集成,提升开发效率。这些核心技术为构建复杂游戏逻辑提供了可靠支撑,尤其在Unreal Engine 5中,UObject架构与TSharedPtr等工具形成了独特的基础设施。本文聚焦UE5 C++开发,深入解析UObject、反射宏与智能指针的协作原理,并通过模块化技能系统案例,展示如何运用TArray、TMap等容器实现数据驱动设计

weixin_33798152的博客 320

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Node-RED 数据处理实战手册:JSON、XML、CSV 的互转与排错

Node-RED 的数据处理,主要靠核心解析器里的一组节点完成:JSON、XML、CSV(还有 HTML、YAML),它们能把 msg 里的字符串、对象和表格数据互相转换。这篇文章不按"技巧清单"罗列,而是跟着一条数据在流程里走完全程:怎么从字符串变成对象,怎么在 XML 和 CSV 之间互转,字段对不上或坏消息出现时怎么办,最后再看怎么提速。 ## 数据入口:三步把 JSON 字符串解析成对象

gitblog_00964的博客 1058

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

掌握yaml-cpp:C++开发者必备的YAML解析与生成终极指南

在当今的C++开发世界中,配置文件、数据序列化和API交互都离不开YAML格式的支持。yaml-cpp作为C++领域最强大、最成熟的YAML解析库,为开发者提供了完整的YAML 1.2规范实现。无论你是处理复杂的配置文件、构建微服务架构,还是需要高效的数据序列化方案,掌握yaml-cpp都将让你的C++项目如虎添翼。 ## 为什么yaml-cpp是C++项目的首选YAML解决方案? yaml-

gitblog_00715的博客 276

【C++智能指针】01_走入智能指针

在实际的C++开发中,我们经常会遇到诸如程序运行中突然崩溃、程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的。有些内存资源已经被释放,但指向它的指针并没有改变指向(成为了野指针),并且后续还在使用;有些内存资源已经被释放,后期又试图再释放一次(重复释放同一块内存会导致程序运行崩溃);没有及时释放不再使用的内存资源,造成内存泄漏,程序占用的内存资源越来越多。智能指针是用于存储动态分配对象指针的类,能自动释放对象,避免堆内存泄漏。

bliu2_10的博客 948

解析 C++ 智能指针的奇特之处

在现代编程中,智能指针是高效内存管理的利器。无论是初学者还是资深开发者,掌握智能指针的奥秘都能让你的代码更加优雅、安全。这篇文章将带你快速了解智能指针的基础概念,深入剖析三种常见智能指针的使用方法,并探索它们的应用场景。快来一起解锁智能指针的魔法吧!✨。

CoderAlice 1133

【CPP】CPP经典面试题

多重继承可能导致菱形继承问题(Diamond Problem),即一个类从两个基类继承,而这两个基类又共同继承自同一个基类,导致派生类中包含多个相同的基类子对象。虚函数是用于实现多态的机制。显式特化是为特定类型提供完全不同的实现,而部分特化是为特定类型的一部分提供不同的实现。显式特化是为特定类型提供完全不同的实现,而部分特化是为特定类型的一部分提供不同的实现。RAII 原则是指将资源的生命周期与对象的生命周期绑定,通过对象的构造函数获取资源,通过析构函数释放资源,确保资源在对象销毁时自动释放。

Ape's IT Blog 1883

C++编程艺术从基础语法到高性能开发实战

本文将通过系统化的方式,从语法基础到实战优化,手把手带领读者突破认知壁垒,掌握高性能C++开发的核心技术。掌握这份从语法底层到系统架构的完整技术栈,开发者就能构建出可在百万级QPS下稳定运行的分布式系统,或是在移动设备上流畅运行的高性能游戏引擎。好的,我将按照您的要求撰写一篇从C++基础语法到高性能开发实战的深度原创文章。

ryjHnPPD的博客 356

[置顶]C++ 引用计数技术及智能指针的简单实现

一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧)。最近花了点时间认真看了智能指针,特地来写这篇文章。 智能指针是什么 简单来说,智能指针是一个类,它对普通指针进行封装,使智能指针类对象具有普通指针类型一样的操作。具体而言,复制对象时,副本和原对象都指向同一存储区域,如果通过一个副本改变其所指的值,则通过另一对象访问的值也会改变.所不同的是,智能指针能够对

melonstreet的专栏 460

C++智能指针详解

智能指针有多智能?

小白成长之路 1万+

C++基础智能指针

独占智能指针会“拥有”它所指向的对象,某一时刻,只能有一个unique_ptr指向给定的对象,当该指针被销毁时,指向的对象也会随之释放。shared_ptr共享他指向的对象,多个共享指针可以指向(关联)相同的对象,在内部采用计数器机制来实现当新的shared_ptr与对象关联时,引用计数器增加1当shared_ptr超出作用域时,引用计数器减1,当引用计数器变为0时,则表示没有任何shared_ptr与对象关联,则释放该对象​class Testpublic://名字。

没有百宝袋的哆啦A梦的博客 2058

[cpp] 智能指针

cpp--智能指针详解

BinaryWiker的博客 1223
上一篇: C++开发基础——函数模板
下一篇: C++开发基础——函数指针&回调函数
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员与背包客_CoderZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值