ADO智能指针使用详解

合集下载

智能指针

智能指针

智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露。

它的一种通用实现技术是使用引用计数(reference count)。

智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。

每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。

智能指针就是模拟指针动作的类。

所有的智能指针都会重载-> 和* 操作符。

智能指针还有许多其他功能,比较有用的是自动销毁。

这主要是利用栈对象的有限作用域以及临时对象(有限作用域实现)析构函数释放内存。

当然,智能指针还不止这些,还包括复制时可以修改源对象等。

智能指针根据需求不同,设计也不同(写时复制,赋值即释放对象拥有权限、引用计数等,控制权转移等)。

auto_ptr 即是一种常见的智能指针。

智能指针通常用类模板实现:[cpp]view plain copyprint?1.template <class T>2.class smartpointer3.{4.private:5. T *_ptr;6.public:7. smartpointer(T *p) : _ptr(p) //构造函数8. {9. }10. T& operator *() //重载*操作符11. {12. return *_ptr;13. }14. T* operator ->() //重载->操作符15. {16. return _ptr;17. }18. ~smartpointer() //析构函数19. {20. delete _ptr;21. }22.};实现引用计数有两种经典策略,在这里将使用其中一种,这里所用的方法中,需要定义一个单独的具体类用以封装引用计数和相关指针:[cpp]view plain copyprint?1.// 定义仅由HasPtr类使用的U_Ptr类,用于封装使用计数和相关指针2.// 这个类的所有成员都是private,我们不希望普通用户使用U_Ptr类,所以它没有任何public成员3.// 将HasPtr类设置为友元,使其成员可以访问U_Ptr的成员4.class U_Ptr5.{6. friend class HasPtr;7.int *ip;8.size_t use;9. U_Ptr(int *p) : ip(p) , use(1)10. {11. cout << "U_ptr constructor called !" << endl;12. }13. ~U_Ptr()14. {15. delete ip;16. cout << "U_ptr distructor called !" << endl;17. }18.};HasPtr类需要一个析构函数来删除指针。

[C++11新特性]智能指针详解

[C++11新特性]智能指针详解

[C++11新特性]智能指针详解C++ 程序设计中使⽤堆内存是⾮常频繁的操作,堆内存的申请和释放都由程序员⾃⼰管理。

但使⽤普通指针,容易造成内存泄露(忘记释放)、⼆次释放、程序发⽣异常时内存泄露等问题等。

所有 C++11 就引⼊了智能指针。

⼀、原始指针容易发⽣内存泄漏C 语⾔中最常使⽤的是函数分配内存,函数释放内存,⽽ C++ 中对应的是、关键字。

只是分配了内存,⽽则更进⼀步,不仅分配了内存,还调⽤了构造函数进⾏初始化。

使⽤⽰例:malloc()free()new delete malloc()new int main(){// malloc 返回值是 void* int* argC = (int*)malloc(sizeof(int)); free(argC);char *age = new int(25); // 做了两件事情 1.分配内存 2.初始化delete age;}和必须成对出现,有时候是不⼩⼼忘记了,有时候则是很难判断在这个地⽅⾃⼰是不是该,这个和资源的⽣命周期有关,这个资源是属于我这个类管理的还是由另外⼀个类管理的(其它类可能要使⽤),如果是别⼈管理的就由别⼈。

new delete delete delete delete 如果需要⾃⼰管理内存的话,最好显⽰的将⾃⼰的资源传递进去,这样的话,就能知道是该资源确实应该由⾃⼰来管理。

char *getName(char* v, size_t bufferSize) {//do somethingreturn v;}上⾯还是⼩问题,⾃⼰⼩⼼⼀点,再仔细看看⽂档,还是有机会避免这些情况的。

但是在 C++ 引⼊异常的概念之后,程序的控制流就发⽣了根本性的改变,在写了 delete 的时候还是有可能发⽣内存泄漏。

如下例:void badThing(){throw 1;// 抛出⼀个异常}void test() { char* a = new char[1000];badThing();// do somethingdelete[] a;}int main() { try { test();}catch (int i){cout << "error happened " << i << endl;}}上⾯的和是成对出现的,但是程序在中间的时候抛出了异常,由于没有⽴即捕获,程序从这⾥退出了,并没有执⾏到,内存泄漏还是发⽣了。

ado使用详解

ado使用详解

ADO(ActiveX Data Objects)是一种用于访问和操作数据的技术,它提供了一种在应用程序中处理数据的方式。

以下是ADO使用详解:
1. 创建ADO对象:在使用ADO之前,需要在代码中创建ADO对象。

可以使用ADO的类来创建不同的对象,如Connection对象、Command对象和Recordset对象。

2. 连接数据库:使用Connection对象可以建立与数据库的连接。

连接数据库需要提供连接字符串,该字符串包含了连接数据库所需的所有信息,如数据源名称、用户名和密码等。

3. 执行SQL查询:通过Command对象可以执行SQL查询。

将SQL查询语句传递给Command对象的Execute方法,即可执行查询并将结果存储在Recordset对象中。

4. 处理Recordset对象:Recordset对象表示查询结果中的一组记录。

可以通过Recordset对象的方法和属性来访问、修改和操作记录。

例如,可以使用Recordset对象的MoveNext和MovePrevious方法来遍历记录集中的记录。

5. 关闭连接:在完成对数据库的操作后,需要关闭与数据库的连接。

可以使用Connection对象的Close方法来关闭连接。

6. 错误处理:在使用ADO时,可能会遇到各种错误。

为了处理这些错误,可以使用ADO的错误对象来获取错误的详细信息,并根据需要进行处理。

以上是ADO使用详解的简要介绍,需要注意的是,使用ADO时
需要根据具体情况选择适当的方法和属性来操作数据,同时需要注意错误处理和资源管理,以确保应用程序的稳定性和可靠性。

一文掌握C++智能指针全部用法

一文掌握C++智能指针全部用法

⼀⽂掌握C++智能指针全部⽤法⽬录⼀、为什么要使⽤智能指针⼆、auto_ptr三、unique_ptr四、shared_ptr五、weak_ptr六、智能指针的使⽤陷阱七、总结为什么要学习智能指针?咳咳,这个问题不是问⼤家的,是询问我⾃⼰的!我依稀记得刚离校出来找实习⼯作那会,去⾯试⼀份⼯作,其中有⼀个环节需要答题;有⼀道题⽬就是问什么是智能指针?卧槽?当时我就懵逼,智能指针我压根就没有听说过…最后,⾯试的这份⼯作理所应当的黄了。

差不多是⼀年前左右吧,现在趁有闲余时间,学习⼀下智能指针,丰富⼀下⾃⼰!⼀、为什么要使⽤智能指针⼀句话带过:智能指针就是帮我们C++程序员管理动态分配的内存的,它会帮助我们⾃动释放new出来的内存,从⽽避免内存泄漏!如下例⼦就是内存泄露的例⼦:#include <iostream>#include <string>#include <memory>using namespace std;// 动态分配内存,没有释放就returnvoid memoryLeak1() {string *str = new string("动态分配内存!");return;}// 动态分配内存,虽然有些释放内存的代码,但是被半路截胡return了int memoryLeak2() {string *str = new string("内存泄露!");// ...此处省略⼀万⾏代码// 发⽣某些异常,需要结束函数if (1) {return -1;}delete str; // 虽然写了释放内存的代码,但是遭到函数中段返回,使得指针没有得到释放return 1;}int main(void) {memoryLeak1();memoryLeak2();return 0;}memoryLeak1函数中,new了⼀个字符串指针,但是没有delete就已经return结束函数了,导致内存没有被释放,内存泄露!memoryLeak2函数中,new了⼀个字符串指针,虽然在函数末尾有些释放内存的代码delete str,但是在delete之前就已经return了,所以内存也没有被释放,内存泄露!使⽤指针,我们没有释放,就会造成内存泄露。

ADO的使用

ADO的使用

开发流程-查询表 开发流程 查询表
【4】执行 】执行SQL命令并取得结果记录集 命令并取得结果记录集
//定义一个指向 定义一个指向Recordset对象的指针 定义一个指向 对象的指针 _RecordsetPtr m_pRecordset; //创建 创建Recordset对象的实例 创建 对象的实例 HRESULT hr; hr = pRentRecordset.CreateInstance(__uuidof(Recordset)); if(FAILED(hr)) { AfxMessageBox(_T("记录集实例化失败,不能初始化 记录集实例化失败, 控件! 记录集实例化失败 不能初始化List控件!")); 控件 return; }
开发流程-连接库 开发流程 连接库
Connection对象除 对象除Open方法外还有许多方法,我们先 方法外还有许多方法, 对象除 方法外还有许多方法 介绍Connection对象中两个有用的属性: 对象中两个有用的属性: 介绍 对象中两个有用的属性 ConnectionTimeOut与State: 与
ADO库包含三个智能指针 库包含三个智能指针: 库包含三个智能指针 _ConnectionPtr、_CommandPtr和_RecordsetPtr。 、 和 。
_ConnectionPtr通常被用来创建一个数据连接或执行一条不返回任何结果 通常被用来创建一个数据连接或执行一条不返回任何结果 语句, 的SQL语句,如一个存储过程。 语句 如一个存储过程。 _CommandPtr返回一个记录集。它提供了一种简单的方法来执行返回记录 返回一个记录集。 返回一个记录集 集的存储过程和SQL语句。在使用 语句。 接口时, 集的存储过程和 语句 在使用_CommandPtr接口时,可以利用全局 接口时 _ConnectionPtr接口,也可以在 接口, 接口里直接使用连接串。 接口 也可以在_CommandPtr接口里直接使用连接串。 接口里直接使用连接串 _RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供 是一个记录集对象。与以上两种对象相比, 是一个记录集对象 了更多的控制功能,如记录锁定、游标控制等。 了更多的控制功能,如记录锁定、游标控制等。

智能指针介绍

智能指针介绍

智能指针介绍⼀、智能指针的作⽤:在C++中,动态内存的管理是⽤⼀对运算符完成的:new和delete,new:在动态内存中为对象分配⼀块空间并返回⼀个指向该对象的指针,delete:指向⼀个动态独享的指针,销毁对象,并释放与之关联的内存。

动态内存管理经常会出现三种问题:1、申请之后忘记释放内存,会造成内存泄漏;2、另⼀种是尚有指针引⽤内存的情况下就释放了它,就会产⽣引⽤⾮法内存的指针。

3、还有⼀种是内存的⼆次释放,即对同⼀个指针进⾏两次 free() 操作,可能导致程序崩溃智能指针的作⽤就是解决上述三种可能出现的问题,指针指针的使⽤效率不会⽐⼀般的指针⾼,但是它胜在更安全、更稳定⼆、智能指针的本质智能指针的实质是⼀个类对象,它是利⽤模板类对⼀般的指针进⾏封装,在类内的构造函数实现对指针的初始化,并在析构函数⾥编写delete语句删除指针指向的内存空间。

这样在程序过期的时候,对象会被删除,内存会被释放,实现指针的安全使⽤。

三、智能指针的类型和使⽤智能指针是在C++11版本之后提供,包含在头⽂件#include<memory>中,智能指针有四种类型,分别是shared_ptr、unique_ptr、auto_ptr、weak_ptr,这⾥只介绍前两种每种指针都有不同的使⽤范围,unique_ptr指针优于其它两种类型,除⾮对象需要共享时⽤shared_ptr。

如果你没有打算在多个线程之间来共享资源的话,那么就请使⽤unique_ptr。

1、shared_ptrshared_ptr可以将多个指针指向相同的对象(共享)。

shared_ptr使⽤引⽤计数,每⼀个shared_ptr的拷贝都指向相同的内存。

每使⽤他⼀次,对象的引⽤计数加1,每析构⼀次,对象的引⽤计数减1,减为0时,⾃动删除所指向的堆内存。

shared_ptr内部的引⽤计数是线程安全的,但是对象的读取需要加锁。

shared_ptr的初始化智能指针是个模板类,可以指定类型,传⼊指针通过构造函数初始化。

ADO使用详解

ADO使用详解

ADO使用详解Connection对象C o n n e c t i o n对象是使我们能与数据存储相连的对象。

只有C o n n e c t i o n对象才能指定希望使用的OLE DB提供者、连接到数据存储的安全细节以及其他任何连接到数据存储特有的细节。

不必显式创建一个C o n n e c t i o n对象以连接到数据存储。

没有C o n n e c t i o n对象,一样可以创建C o m m a n d、R e c o r d s e t和R e c o r d对象。

如果不创建自己的C o n n e c t i o n对象,A D O将会隐含地为你创建一个C o n n e c t i o n对象。

如果要对提供者运行多条命令,应该显式地创建一个C o n n e c t i o n对象,这比每运行一条命令就创建一个连接更有效。

除了为数据存储提供连接以外,C o n n e c t i o n对象允许针对数据存储执行命令操作。

这些命令可以是结构化的或存储的命令(例如,S Q L命令或一个存储过程),并且可以有选择地从数据存储中返回一些数据。

Command对象C o m m a n d 对象是对数据存储执行命令的对象。

看到这里读者可能会产生疑问,C o n n e c t i o n对象不也能这样做吗?是的,但是C o n n e c t i o n对象在处理命令的功能上受到一定的限制,而C o m m a n d对象是特别为处理命令的各方面问题而创建的。

当从C o n n e c t i o n对象中运行一条命令时,已经隐含地创建了一个C o m m a n d对象。

有时其他对象允许向命令传入参数,但在C o n n e c t i o n对象中不能指定参数的任何细节。

使用C o m m a n d对象允许指定参数(以及输出参数和命令执行后的返回值)的精确细节(比如,数据类型和长度)。

智能指针的应用原理

智能指针的应用原理

智能指针的应用原理1. 什么是智能指针智能指针是C++中的一个特性,用于管理动态分配的内存。

与原始指针(raw pointer)不同的是,智能指针有能力自动管理所指的内存,避免内存泄漏和野指针的问题。

智能指针通过在析构函数中释放所引用的内存来确保资源的正确释放,从而减少错误和内存泄露的风险。

2. 智能指针的优点•自动释放内存:智能指针可以自动释放所管理的内存,避免了手动释放内存的繁琐工作,并减少了内存泄漏的风险。

•简化内存管理:智能指针可以方便地共享和传递资源所有权,减少了手动处理内存所有权的复杂性。

•防止野指针:智能指针会在指针不再需要时自动将其置为nullptr,避免了野指针的问题。

•可定制性:C++提供了多个智能指针类型,如unique_ptr、shared_ptr和weak_ptr,每种智能指针类型都有自己的适用场景,开发人员可以根据需要选择使用不同类型的智能指针。

3. 智能指针的应用场景智能指针在以下情况下特别有用:1.动态内存分配:当需要动态分配内存时,使用智能指针可以方便地管理所分配的内存,避免内存泄漏和野指针的问题。

2.资源管理:智能指针可以用于管理其他类型的资源,如文件句柄、数据库连接等,通过在析构函数中释放资源,确保资源的正确释放。

3.避免循环引用:shared_ptr和weak_ptr可以用于解决循环引用的问题。

当存在互相引用的对象时,如果使用普通指针,则这些对象无法被正确释放,而使用shared_ptr和weak_ptr可以解决这个问题。

4. 智能指针的工作原理智能指针通过维护一个引用计数(reference count)来管理内存。

引用计数表示有多少个指针共享同一块内存。

•unique_ptr使用独占的方式管理内存,即同一时间只能有一个指针指向该内存。

•shared_ptr可以共享内存,通过维护一个引用计数,当引用计数为0时,释放内存。

•weak_ptr是一种弱引用指针,它不会增加引用计数,也不能直接访问内存,主要用于解决循环引用的问题。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ADO智能指针使用详解一、ADO接口——Connection对象(连接对象)——对应智能指针为_ConnectionPtr在使用ADO进行操作之前,必须使用AfxOleInit()函数来进行初始化。

使用BeginTrans、CommitTrans和RollbackTrans方法可以启动、提交和回滚一个处理事务。

通过操作the Errors 集合可以获取和处理错误信息,操作CommandTimeout属性可以设置连接的溢出时间,操作ConnectionString属性可以设置连接的字符串,操作Mode属性可以设置连接的模式,操作Provider属性可以指定OLE DB提供者。

(1)Open()方法:用于打开一个库连接_ConnectionPtr智能指针的用法:①首先定义一个Connection类型的指针,然后调用CreateInstance()来创建一个连接对象的实例,再调用Open()函数建立与数据源的连接。

②在建立连接对象后,可以使用连接对象的Execute()函数来执行SQL命令。

_ConnectionPtr智能指针Open()方法的原型:Open(_bstr_t ConnectionString,_bstr_t UserID,_bstr_t Password,long Options)①ConnectionString为连接字串,UserID是用户名,Password是登陆密码②Options是连接选项,可以是如下几个常量:1> adModeUnknown 缺省,当前的许可权未设置2> adModeRead 只读3> adModeWrite 只写4> adModeReadWrite 可以读写5> adModeShareDenyRead 阻止其它Connection对象以读权限打开连接6> adModeShareDenyWrite 阻止其它Connection对象以写权限打开连接7> adModeShareExclusive 阻止其它Connection对象打开连接8> adModeShareDenyNone 阻止其它程序或对象以任何权限建立连接(2)Execute()方法:用于执行SQL语句函数原型:_RecordsetPtr Connection::Execute(_bstr_t CommandText,VARIANT* RecordsAffected,long Options)参数:①CommandText是命令字串,通常是SQL命令,②RecordsAffected是操作完成后所影响的行数③Options表示CommandText中内容的类型,可以取下列值之一:1> adCmdText 表明CommandText是文本命令2>adCmdTable 表明CommandText是一个表名3>adCmdProc 表明CommandText是一个存储过程4>adCmdUnknown 未知Execute执行完后返回一个指向记录集的指针(_ResultsetPtr类型)(3)异常捕获:出现的异常为_com_errorError对象包含了ADO数据操作时发生错误的详细描述,ADO的任何对象都可以产生一个或者多个数据提供者错误,当错误发生时,这些错误对象被添加到Connection 对象的Errors集合里。

当另外一个ADO对象产生一个错误时,Errors集合里的Error对象被清除,新的Error对象将被添加到Errors集合里。

借助于Errosr对象的集合、方法和属性,可以通过读取Number和Description属性,获得ADO错误号码和对错误的描述,通过读取Source属性得知错误发生的源。

二、ADO接口——Recordset对象(记录集对象)——对应智能指针为_RecordsetPtr_RecordsetPtr智能指针,它是专门为通过记录集操作数据库而设立的指针,通过该接口可以对数据库的表内的记录、字段等进行各种操作。

记录集相当于是实际数据的一份拷贝。

A.创建记录集对象_ConnectionPtr m_pRecordset;m_pRecordset.CreateInstance(__uuidof(Recorset));创建记录集对象,只是为它分配内存空间,记录集中不含任何数据。

B.打开记录集记录集对象是用来获得数据库中的数据并对其操作的,所以还要打开记录集,从数据库中取得数据记录。

可有多种方法打开记录集,如使用_CommondPt::.Execute()来返回一个记录集,或是用_Recordset::Open()方法来打开一个记录集。

(1)Open()方法函数原型:HRESULT Recordset::Open(const _variant_t&Source,const_variant_t&ActiveConnection,enum CursorTypeEnum CursorType,enum LockTypeEnum LockType,long Options)For Example:假设m_pConnection是已经建立好的连接,我们使用_RecordsetPtr 接口的Open方法打开Employees表的记录集的语句如下:m_pRecordset->Open("SELECT * FROM Employees", _variant_t((IDispatch*)m_pConne ction,true), adOpenStatic, adLockOptimistic, adCmdText);参数:Source是数据查询字符串,可以是一个SQL语句、一个表的名字或一个命令对象等等;ActiveConnection是已经建立好的连接(我们需要用Connection对象指针来构造一个_variant_t对象);CursorType光标类型,它是枚举CursorTypeEnum中的一个值,可取如下值之一:adOpenUnspecified=-1 不作特别指定adOpenForwardOnly=0 默认值,前滚静态光标。

(这种光标只能向前浏览记录集,比如用MoveNext向前滚动,这种方式可节省资源,提高浏览速度,但诸如BookMark、RecordCount、AbsolutePosition、AbsolutePage都不能使用。

)adOpenKeyset=1 键集游标,采用这种光标的记录集看不到其它用户的新增、删除操作,但对于更新原有记录的操作对你是可见的。

adOpenDynamic=2 动态光标,所有数据库的操作都会立即在用户记录集上反应出来。

adOpenStatic=3 静态游标。

它为记录产生一个静态备份,其他用户的新增、删除、更新操作对你的记录集来说是不可见的。

LockType锁定类型,它是枚举LockTypeEnum中的一值,可以是以下值之一 enum LockTypeEnum{adLockUnspecified=-1, //未指定adLockReadOnly=1,//只读记录集,默认值。

无法更改数据。

adLockPessimistic=2,//悲观锁定方式。

只有在调用Update方法时才锁定记录。

这是最安全的锁定机制adLockOptimistc=3,//乐观锁定方式,只有在你调用Update方法时才锁定记录。

adLockBatchOptimistic=4//乐观分批更新。

编辑时记录不会锁定,更改、插入及删除是在批处理模式下完成。

}Options指定Source的类型,可以取如下值之一:adCmdText: 表明CommandText是文本命令。

adCmdTable: 表明CommandText是一个表名。

adCmdProc: 表明CommandText是一个存储过程。

adCmdUnknown: 未知。

C.指针的移动移动记录指针可以通过MoveFirst()方法移动到第一条记录,MoveLast()方法移动到最后一条记录,MovePrevious()方法移动到当前记录的前一条记录,MoveNext()方法移动到当前记录的下一条记录。

也可以使用Move(记录号)移动记录指针到需要位置。

注意:Move()方法是相对于当前记录来移动指针位置的。

正值向后移动,负值向前移动。

如Move(3),当前记录是3时,它将从记录3开始往后再移动3条记录位置。

两个_RecordsetPtr属性:BOF 属性表示记录集第一条记录之前的游标,用来判断记录集是否为空EOF(通常会rename为adoEOF)属性表示记录集最后一条记录之后的游标,用来判断是否结束D.数据的读取GetCollect(字段名)来获取当前记录指针所指的字段值返回值的类型为:_variant_tE.数据的更新:用PutCollect(字段名,值)将新值写入,并Update()更新到数据库。

F.插入记录先移动记录指针到要插入的位置,用AddNew()插入一条记录,然后用PutCollect(字段名,值)写入值,最后用Update()更新到数据库;G.删除记录删除单条记录:先移动记录指针到合适的位置,然后用Delete()方法删除它(取参数adAffectCurrent,表示操作只影响当前的记录),并用Update()来更新数据库;H.关闭记录集直接用Close()方法关闭记录集并赋予其空值。

代码如下:m_pRecordset->Close();m_pRecordset=NULL;类似于_ConnectionPtr的关闭方法;(2). 取得一个字段的值的两种办法A、表示取得第0个字段的值m_pRecordset->GetCollect(“Name”);B、或者m_pRecordset->GetCollect(_variant_t(long(0));三、ADO接口——Command对象(记录集对象)——对应智能指针为_CommandPtrCommand对象是一个对数据源执行命令的定义,使用该对象可以查询数据库并返回一个Recordset对象,可以执行一个批量的数据操作,可以操作数据库的结构。

不同的数据提供者提供的该对象的集合、方法和属性不同。

借助于Command对象的集合、方法和属性,可以使用Parameters集合制定命令的参数,可以使用Execute方法执行一个查询并将查询结果返回到一个Recordset对象里,操作CommandText属性可以为该对象指定一个命令的文本,操作CommandType属性可以指定命令的类型,操作Prepared可以得知数据提供者是否准备好命令的执行,操作CommandTimeout属性可以设置命令执行的溢出时间。

相关文档
最新文档