1.3.1 智能指针

osge阶段学习总结3(给自己看的记录)——OSG 智能指针 详解 osge阶段学习总结3(给自己看的记录)——OSG 智能指针 详解1、Referenced类2、ref_ptr类。3、调用实例说明。3.1、create1()函数:3.2、create2()函数:3.3、create3()函数:4、额外推荐5、最后 注:osg版本号为3.6.3 1、Referenced类 osg::Referenced类是几乎所有osg类的父类。 这个类与智能指针修改部分函数如下:(不相关函数略) class OSG_EXPORT Referenced { public: 阅读详情

智能指针

为什么要使用智能指针

  1. 内存泄露:内存手动释放,使用智能指针可以自动释放。
    malloc了就要free,new了就要delete,很麻烦。
  • 类内的指针,在析构函数里释放
  • 堆区里c++内置数据类型,没有析构函数怎么办?—手工delete
  • new出来的类,必须要detele才能调用析构函数,又容易忘记
  1. 共享所有权指针的传播和释放,比如多线程使用同一个对象时析构问题
    在这里插入图片描述
    多个只读线程需要访问同一个数据帧,如果全是深拷贝就很浪费资源,如果全是浅拷贝,就会在第一个访问结束后,释放该数据帧,其他线程就访问不到了。
  • 智能指针是类模板对象,在栈上创建智能指针对象
  • 把普通指针交给智能指针对象
  • 智能指针过期时,调用析构函数释放普通指针的内存

unique_ptr

定义:意思是unique_ptr独享它指向的对象,也就是说同时只有一个unique_ptr指向同一个对象,当这个unique_ptr被销毁时,它指向的对象也随即被销毁
包含头文件:include
在这里插入图片描述

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

class AA {
public:
	string m_name;
	AA() { cout << m_name << "调用构造函数AA()" << endl; }
	AA(const string &name):m_name(name) { cout << "调用构造函数AA("<<m_name<<")" << endl; }
	~AA() { cout << "调用析构函数AA(" << m_name << ")" << endl; }

};

int main() {
	AA* p = new AA("西施");
	//创建AA类型的智能指针pu1来管理p
	unique_ptr<AA> pu1(p);
	//delete p;
}

即使不使用delete来删除p指针,智能指针也会调用析构函数
原因是:智能指针是类,它有析构函数
在这里插入图片描述
初始化方法一:unique_ptr<AA> p0(new AA("西施"));
初始化方法二: unique_ptr<AA> p0 = make_unique<AA>("西施");
初始化方法三:AA* p = new AA("西施"); unique_ptr<AA> p0(p);

1)使用细节

  • 智能指针重载了*和->操作符,可以和使用指针一样使用*和->
  • 不支持普通的拷贝和赋值
  • 不要用同一个裸指针初始化多个unique_ptr对象(所以初始化方法一比初始化方法三更安全)
int main() {
	AA* p = new AA("西施");
	unique_ptr<AA> pu(p);
	
	cout << "         裸指针的值是:" << p << endl;
	cout << "       pu的输出结果是:" << pu << endl;
	cout << " pu.get()的输出结果是:" << pu.get() << endl;
	cout << "         pu的地址值是:" << &pu << endl;
}

在这里插入图片描述

2)用于函数的参数

  • 传引用
void func(unique_ptr<AA> pp) {
	cout << "name = " << pp->m_name << endl;
}


int main() {
	AA* p = new AA("西施");
	
	unique_ptr<AA> pu(p);

	func(pu);
	return 0;
}

func(pu); 报错------因为智能指针拷贝构造函数已经被删除
改为传引用------在void func(unique_ptr<AA> pp)中的pp前面
加上&即可 void func(unique_ptr<AA> &pp)

  • 裸指针
  • 不支持指针的运算(+,-,++,–)

3)更多技巧

1) 将一个unique_ptr 赋给另一个时,如果原unique_ptr是一个临时右值,编译器允许这样做(即使本来operator=是被禁掉了的),但如果是要存在一段时间就不行,一般是作为函数返回值。
2)用nullptr给unique_ptr赋值将释放对象,空的unique_ptr == nullptr.

int main() {
	
	unique_ptr<AA> pu(new AA("西施"));

	if (pu != nullptr) cout << "pu非空" << endl;
	pu = nullptr;
	if (pu == nullptr) cout << "pu为空" << endl;
	return 0;
}

在这里插入图片描述

3)release()释放对原始指针的操控权,将unique_ptr置为空,返回裸指针。
4)std::move()可以转移对原始指针的控制权。(可以用于把unique_ptr传递给子函数,子函数形参也是unique_ptr)
测试代码一:

void func1(const AA* a) { // func1需要一个指针,但不对该指针负责
	cout <<a->m_name << endl;
}

int main() {
	unique_ptr<AA> pu(new AA("西施"));
	func1(pu.get());//构造->西施->析构
	return 0;
}

测试代码二:

void func2(AA * a) { // func2需要一个指针,并且对该指针负责
	cout <<a->m_name << endl;
	delete a;
}

int main() {
	unique_ptr<AA> pu(new AA("西施"));
	func2(pu.release());// 此时就释放了原指针的控制权,并且自己变成空
	return 0;
}

测试代码三:

void func3(const unique_ptr<AA> &a) { // func3需要一个unique_ptr,不会对unique_ptr负责
	cout <<a->m_name << endl;
}

int main() {
	unique_ptr<AA> pu(new AA("西施"));
	func3(pu);
	return 0;
}

测试代码四:

void func4(const unique_ptr<AA> a) { // func4需要一个unique_ptr,并且会对unique_ptr负责
	//使用传值的方法,而不是传引用
	cout <<a->m_name << endl;
}

int main() {
	unique_ptr<AA> pu(new AA("西施"));
	func4(move(pu));//使用move将控制权递交
	return 0;
}

5)swap()交换两个unique_ptr的控制权
void swap(unique_ptr<T> &_Right);
6)unique_ptr和普通指针一样具有多态的特性
7)智能指针也不是绝对安全,如果程序中调用exit()退出,全局的unique_ptr可以自动释放,但局部的unique_ptr无法释放;

unique_ptr<AA> pu1(new AA("全局"));

int main() {
	unique_ptr<AA> pu2(new AA("局部"));
	return 0;//换成exit(0);
}

在这里插入图片描述

在这里插入图片描述

8)提供了支持数组的具体化版本。
数组版本的unique_ptr,重载了操作符[ ],[ ]返回的是引用,可以作为左值使用。

int main() {
	unique_ptr<AA[]> parrs(new AA[2]);
	parrs[0].m_name = "西施";
	parrs[1].m_name = "貂蝉";

	cout << "parrs[0].m_name = " << parrs[0].m_name << endl;
	cout << "parrs[1].m_name = " << parrs[1].m_name << endl;

}

在这里插入图片描述

shared_ptr

定义:shared_ptr共享它指向的对象,多个shared_ptr可以指向(关联)相同的对象,内部采用计数器机制实现。
当新的shared_ptr与对象关联时,计数器+1
当shared_ptr超过作用域时,计数器-1,当计数器为0时,表示没有任何shared_ptr与对象关联,则释放该对象。
shared_ptr并没有删除拷贝构造函数和赋值函数,因为它需要。

1)初始化

方法一:
shared_ptr<AA> p0(new AA("西施"));//分配内存并初始化
方法二:
shared_ptr<AA> p0 = make_shared<AA>("西施");
方法三:
AA* p = new AA("西施"); shared_ptr<AA> p0(p);
方法四:

	shared_ptr<AA> p0(new AA("西施"));
	shared_ptr<AA> p1(p0); //使用构造函数
	shared_ptr<AA> p2 = p0;//使用赋值函数

2)使用方法

  • use_count()返回计数器的值
  • unique()判断计数器的值是不是1,是返回true,不是返回false
  • get()返回裸指针
  • 不要用同一个裸指针初始化多个shared_ptr
  • 不要用shared_ptr管理不是new分配的内存

3)用于函数的参数

基本上和unique_ptr一样

4)不支持指针的运算(+,-,++,–)

5)线程安全性

  • shared_ptr的计数器本身是线程安全的(计数是原子操作)
  • 多个线程同时读同一个shared_ptr对象是线程安全的
  • 如果多个线程同时对同一个shared_ptr对象进行读和写,需要加锁
  • 多个线程读写多个shared_ptr对象,如果这些shared_ptr对象指向的是同一个对象,那么也需要加锁

6)效率比较

如果unique_ptr能解决问题,就不要用shared_ptr,unique_ptr的效率更高,需要的资源更少。

7)智能指针的删除器

默认情况下,智能指针过期时,使用delete原始指针,释放它管理的资源
程序员可以自定义删除器,改变智能指针释放资源的行为
删除器可以是全局函数,仿函数,Lamda表达式,形参为原始指针

  • 普通函数
void deletefunc(AA* a) {
	cout << "自定义删除器(全局函数)" << endl;
	delete a;

}

int main() {
	shared_ptr<AA> p0(new AA("西施"),deletefunc);
}

在这里插入图片描述

  • 仿函数
struct deleteclass {
	void operator()(AA *a) {
		cout << "自定义删除器(仿函数)" << endl;
		delete a;
	}
};


int main() {
	shared_ptr<AA> p0(new AA("西施"),deleteclass());
}

在这里插入图片描述

  • Lambda表达式
auto deleterlamb = [](AA* a) {
	cout << "自定义删除器(Lambda)" << endl;
	delete a;
	};

int main() {
	shared_ptr<AA> p0(new AA("西施"),deleterlamb);
}

在这里插入图片描述

  • unique_ptr的删除器与shared_ptr删除器的区别
unique_ptr<AA,void(*)(AA*)> p0(new AA("西施"), deleterlamb);

weak_ptr

shared_ptr内部维护了一个共享的计数器,多个shared_ptr可以指向同一个资源。但是,如果出现了循环引用的情况,计数器无法归0,资源就不会被释放。
weak_ptr持有但不拥有对象的所有权,通常与shared_ptr一起使用,以避免循环引用导致的内存泄漏问题。

#include<iostream>
#include<vector>
#include<memory>
using namespace std;
class BB;

class AA {
public:
	string m_name;
	AA() { cout << m_name << "调用构造函数AA()" << endl; }
	AA(const string &name):m_name(name) { cout << "调用构造函数AA("<<m_name<<")" << endl; }
	~AA() { cout << "调用析构函数AA(" << m_name << ")" << endl; }
	shared_ptr<BB> m_p;

};
class BB {
public:
	string m_name;
	BB() { cout << m_name << "调用构造函数BB()" << endl; }
	BB(const string& name) :m_name(name) { cout << "调用构造函数BB(" << m_name << ")" << endl; }
	~BB() { cout << "调用析构函数BB(" << m_name << ")" << endl; }
	shared_ptr<AA> m_p;

};

int main() {
	shared_ptr<AA> pa = make_shared<AA>("西施a");
	shared_ptr<BB> pb = make_shared<BB>("西施a");

	pa->m_p = pb;
	pb->m_p = pa;
}

结果并不会释放内存(调用析构函数)
在这里插入图片描述

将其中一个shared_ptr改为weak_ptr就可以打破循环。

//将classAA中的
shared_ptr<BB> m_p;
//改成
weak_ptr<BB> m_p;

在这里插入图片描述

expired函数的用法

expired:判断当前weak_ptr智能指针是否还有托管的对象,有则返回false,无则返回true
如果返回true,等价于 use_count() == 0,即已经没有托管的对象了;当然,可能还有析构函数进行释放内存,但此对象的析构已经临近(或可能已发生)。

重点!!!
weak_ptr不控制对象的生命周期,但它知道对象是否活着。
用lock()函数把它可以提升为shared_ptr,如果对象还活着,返回有效的shared_ptr, 如果对象已经死了,提升会失败,返回一个空的shared_ptr。
提升的行为是线程安全的。

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

相关推荐

iOS逆向实战:绕过SSL Pinning抓取ChatGPT设备令牌

在移动应用安全与网络协议分析领域,中间人攻击是一种核心的流量拦截与分析技术。其原理是在客户端与服务器之间插入一个代理节点,通过伪造数字证书来解密和窥探HTTPS加密流量。这项技术的工程价值在于,它使开发者能够调试API、分析通信协议以及实现自动化集成。然而,许多高安全要求的应用(如金融、社交类App)会采用SSL Pinning(证书绑定)技术来抵御此类攻击,这为逆向工程带来了挑战。本文聚焦于一个具体的应用场景:如何针对启用了SSL Pinning的ChatGPT iOS客户端,通过特定的工具链(如Trol

weixin_28235889的博客 976

C++的智能指针(1/3)

auto_ptr 是c++ 98定义的智能指针模板,其定义了管理指针的对象,可以将new 获得(直接或间接)的地址赋给这种对象。自动释放内存:智能指针使用了RAII(资源获取即初始化)的原则,在创建时分配内存,在销毁时自动释放内存,无需手动管理内存释放,避免了因为忘记释放内存而造成的内存泄漏问题。避免悬挂指针:智能指针会在其所管理的对象不再需要时自动释放内存,并将指针置为空,避免了悬挂指针问题,即指向已经释放的内存区域。智能指针是一种封装了原始指针的对象,它提供了自动内存管理的功能。_cpp智能指针特性。

mumuemhaha的博客 355

AD9361快速锁定实战:Profile寄存器配置与频率调谐算法解析

本文深入解析了AD9361射频收发器的快速锁定(Fast Lock)功能,重点阐述了其核心机制——Profile寄存器配置。通过剖析16字节Profile结构,详细讲解了频率调谐算法,包括LO_DIV、LO_INT、LO_FRAC等关键参数的计算,以及如何通过查表获取优化的环路滤波器参数。文章提供了完整的Python算法示例和FPGA实现要点,旨在帮助工程师实现毫秒级甚至微秒级的频率切换,满足跳频通信等高性能应用需求。

weixin_29196315的博客 229

【深入了解cocos2d-x 3.x】内置数据结构(1)——智能指针

智能指针在C++11的标准中已经存在了,分别是unique_ptr,shared_ptr,weak_ptr,其中最常用的应该是share_ptr,它采用引用计数的方式管理内存,当引用计数为0的时候,自动释放内存,但是由于shared_ptr考虑到了线程安全,所以会存在有较大的性能损失。所以在实时游戏开发中,往往不会用到shared_ptr。 在cocos2d-x3.2以及更高的版本中,cocos

NxShow的博客 1754

电池管理系统(BMS)系列—状态估计之SOH

BMS系列文章,介绍了SOH估计

zxx52113140的博客 1846

用RK3588 NPU加速人脸识别:从本地测试到服务器部署的完整流程(含ONNX模型)

本文详细介绍了如何利用RK3588 NPU加速人脸识别系统,从模型优化到高并发服务部署的全流程。通过RetinaFace和FaceNet模型的协同推理,结合ONNX模型转换和NPU特有优化技巧,显著提升识别效率。文章还涵盖了gRPC通信架构设计、性能压测及实际部署经验,为开发者提供了一套完整的解决方案。

weixin_29058331的博客 465

智能指针,作为函数参数怎么用?

通过上面代码运行,可以发现只有fun1的指针引用在函数调用后有变化。所以智能指针作为函数参数的正确用法,就是传值使用。用智能指针的引用、指针都是不对,无法实现智能指针的引用计数效果。智能指针作为C++很重要的东西,被广泛使用。当智能指针被作为函数参数使用时,应该怎样使用呢?

caz28的专栏 2014

车载仪表-功能点测试大全(超详细,细分可作测试用例)

汽车仪表系统发展经历了机械式、电气化到智能化的演变,目前全液晶仪表渗透率达73.4%。文章详细梳理了仪表功能测试要点,包括UI界面显示一致性、按键响应、FM收音、信号灯显示、USB功能、蓝牙连接、胎压监测、导航系统、WiFi投屏、倒车影像及多媒体播放等关键功能模块的测试标准。特别关注界面切换流畅度、功能稳定性及异常情况处理能力,如投屏状态下是否卡顿、导航中断后能否自动恢复等。测试覆盖了CarPlay、AndroidAuto等主流投屏方案的兼容性验证,确保各类交互场景下的系统可靠性。

weixin_51551002的博客 2067

ComPtr智能指针之美

IUnknown接口类 DirectX11的API是由一系列的COM组件来管理的,这些前缀带I的接口类最终都继承自IUnknown接口类。IUnknown的三个方法如下: 方法 描述 IUnknown::AddRef 内部引用计数加1。在每次复制了一个这样的指针后,应当调用该方法以保证计数准确性 IUnknown::QueryInterface 查询该实例是否实现了另...

游戏开发、游戏引擎开发、逆向破解爱好者 3718

解析vCard 3.0:提取电子名片中的姓名

N:LastName;FirstName;;;END:VCARD和END:VCARD标记数据块的开始和结束。N字段存储结构化姓名(分号分隔)。FN字段为直接可读的显示名称。其他字段如TELEMAIL等保存联系信息。

qq_45797625的博客 2780

自私兽群优化器(SHO)详解:从生物本能到智能优化

自私兽群优化器(SHO)是一种受动物群体自私行为启发的智能优化算法。该算法模拟动物在捕食威胁下的两种行为:聚集行为(全局搜索)和自私行为(局部搜索),将优化问题的解空间映射为生存环境,候选解视为猎物个体。SHO通过安全性评估将猎物分为安全、危险和高危三类,分别采用不同的位置更新策略,并引入捕食者角色增加选择压力。相比传统优化算法,SHO具有无需梯度信息、自适应平衡探索与开发、参数简单等优势,特别适合高维复杂和多模态优化问题。算法通过马尔可夫链理论保证收敛性,已在工程设计和数据挖掘等领域展现出良好性能。

qq_42212808的博客 197

【C++11】智能指针深度详解(什么是智能指针?为什么需要智能指针?如何使用智能指针?)

智能指针这个名词听着挺唬人,其实也没啥,无非就是会自动销毁new出来的对象,对于日常使用来说,还是挺方便的,毕竟C/C++可没有隔壁Java的垃圾回收机制GC,得自己清理垃圾,智能指针可以自动完成垃圾清理这个工作

weixin_45031801的博客 7673

使用MATLAB结合EasySpin进行ESR模拟的详细步骤及示例代码

安装EasySpin:确保你已经安装了EasySpin工具箱,它可以帮助你进行ESR模拟。你可以从EasySpin的官方网站(https://easyspin.org/)下载并安装。准备实验数据:将实验得到的EPR数据整理成合适的格式,一般包含磁场(Magnetic Field)和信号强度(Intensity)两列。进行模拟:使用EasySpin的函数对单线态氧自由基和超氧自由基进行模拟。调整参数:通过调整模拟参数,使模拟得到的峰型和峰位置与实验数据尽可能匹配。导出数据。

AI的内部世界的博客 2005

C++智能指针详解

智能指针有多智能?

小白成长之路 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

智能指针实现

按照自己的使用习惯, 构造了一个智能指针. 一. 深度拷贝的智能指针 // Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" // 深度拷贝的智能指针 // 1. 手动/自动构造对象. // 2. 自动深度赋值 // 3. 自动释放对象(对象内部资源对象自己负责) template class CHYDeepPtr { public

cay22的专栏 818

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

【C++】智能指针

C++中的智能指针,重点讨论了其设计思路、使用场景及标准库中的实现。智能指针基于RAII(资源获取即初始化)原则,通过类的生命周期管理资源,确保资源在异常抛出时仍能正确释放,避免内存泄漏。标准库提供了多种智能指针,如auto_ptr(已弃用)、unique_ptr(独占资源)、shared_ptr(共享资源)和weak_ptr(解决循环引用问题)。shared_ptr通过引用计数管理资源,而weak_ptr则用于打破shared_ptr的循环引用,避免内存泄漏。此外,智能指针还支持删除器,允许自定

记录学习与成长 3212

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

智能指针

什么是智能指针?       智能指针是一个类,这个类的构造函数中传入一个指针,析构函数中释放传入的指针。智能指针都是栈上那个的对象,所以当函数(或程序)结束时都会被自动释放。 为什么要使用智能指针? 在堆区申请空间往往会遇到以下问题: 1、内存被不正确的释放,例如下代码: void fun(int *p) { *p = 5; cout &lt;&lt; *p &lt;...

qq_41727218的博客 295

3、c++智能指针

智能指针的知识点。这部分比较困难,需要仔细看文章,最好自己敲一遍。必须掌握

2401_82911768的博客 1048

【C++11】智能指针

早期在C语言中我们学习了指针,这个指针学起来真是一个头两个大,当然学习到了这里想必大家对指针就不在害怕了,为了填上C++的不足在C++11中就扩展了智能指针,难道智能指针就真的那么智能吗?⭐主体。

AAlykk的博客 1299

Qt 之 智能指针汇总

来源 还有其他一些,做了一些汇总和测试,就不全列了。 文章目录: 一、垂悬指针的问题 二、Qt中的智能指针        1、QPointer        2、QSharedPointer & QWeakPointer        3、QScopedPointer      &n

一个老菜鸟的学习分享 7567

C++智能指针

一、为什么使用智能指针?智能指针的原理? C/C++中的堆内存分配和释放的方式主要是: malloc/free 以及 new/delete 等。 使用new 和delete 管理内存存在三个常见问题: 1.忘记delete(释放) 内存,或者异常导致程序过早退出,没有执行 delete。忘记释放动态内存会导致内存泄露问题,长时间这样会导致系统内存越来越小。(内存泄露问题往往很难查...

ajn1221的博客 213

C++基础智能指针

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

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

12.1.3

12.10 我认为没有问题12.11process(std::shared_ptr<int>(p.get()));会出错,传递给process的是一个临时的智能指针(使用一个内置指针初始化),在函数结束,会被系统释放,从而使p指向的内存被释放了。12.12auto p = new int(); auto sp = std::make_shared<int>(); process(sp);//合法,

PYPARA的博客 359
上一篇: 1.2.2 设计模式(二)
下一篇: GOLANG笔记第三周
fcopy
博客等级 码龄6年 252粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值