c++ 智能指针 (std::auto_ptr)

定义于头文件 <memory>

template< class T > class auto_ptr;

(1)(C++11 中弃用)
(C++17 中移除)

template<> class auto_ptr<void>;

(2)(C++11 中弃用)
(C++17 中移除)

auto_ptr 是通过由 new 表达式获得的对象,并在 auto_ptr 自身被销毁时删除该对象的智能指针。它可用于为动态分配的对象提供异常安全、传递动态分配对象的所有权给函数和从函数返回动态分配的对象。

复制 auto_ptr ,会复制指针并转移所有权给目标: auto_ptr 的复制构造和复制赋值都会修改其右侧参数,而且“副本”不等于原值。因为这些不常见的复制语义,不可将 auto_ptr 置于标准容器中。此用途及其他使用更适合用 std::unique_ptr 。 (C++11 起)

2) 提供对类型 void 的特化,它声明 typedef element_type ,但无成员函数。

文档中到处使用附加的类模板 auto_ptr_ref 。它是保有到 auto_ptr 引用的实现定义类型。允许实现提供拥有不同名称的模板,或以其他方式实现返回它或接受它为参数的函数。

构造函数

std::auto_ptr<T>::auto_ptr

explicit auto_ptr( X* p = 0 ) throw();

(1)(C++11 中弃用)
(C++17 中移除)

auto_ptr( auto_ptr& r ) throw();

(2)(C++11 中弃用)
(C++17 中移除)

template< class Y >
auto_ptr( auto_ptr<Y>& r ) throw();

(3)(C++11 中弃用)
(C++17 中移除)

auto_ptr( auto_ptr_ref<X> m ) throw();

(4)(C++11 中弃用)
(C++17 中移除)

从指代待管理对象的指针构造 auto_ptr

1) 以指针 p 构造 auto_ptr

2) 以 r 所保有的指针构造 auto_ptr 。调用 r.release() 获取该对象的所有权。

3) 同 (2) 。 Y* 必须可隐式转换为 T* 。

4) 以 m 所指代的 auto_ptr 实例中保有的指针构造 auto_ptr 。对 m 所保有的 auto_ptr p 调用 p.release() 以获取该对象的所有权。

auto_ptr_ref 是保有到 auto_ptr 引用的实现定义类型。 std::auto_ptr 可隐式转换成此类型并可从它赋值。允许实现以不同的名称提供该模板,或以其他方式实现等价的功能。

参数

p-指向待管理对象的指针
r-另一 auto_ptr ,从它传递所有权
m-保有到 auto_ptr 的引用的实现定义类型对象

注意

源自 auto_ptr_ref 的构造函数和复制赋值运算符允许从无名临时量复制构造和赋值 std::auto_ptr 。因为其复制构造函数与复制赋值运算符以非 const 引用接收参数,它们不能直接绑定右值。然而能执行用户定义转换(释放原 auto_ptr ),之后再调用以值接收 auto_ptr_ref 的构造函数或复制赋值运算符。这是移动语义的早期实现。

 

析构函数

std::auto_ptr<T>::~auto_ptr

~auto_ptr() throw();

(C++11 中弃用)
(C++17 中移除)

销毁管理的对象。调用 delete get() 。

从另一 auto_ptr 转移所有权

std::auto_ptr<T>::operator=

auto_ptr& operator=( auto_ptr& r ) throw();

(1)(C++11 中弃用)
(C++17 中移除)

template< class Y >
auto_ptr& operator=( auto_ptr<Y>& r ) throw();

(2)(C++11 中弃用)
(C++17 中移除)

auto_ptr& operator=( auto_ptr_ref m ) throw();

(3)(C++11 中弃用)
(C++17 中移除)

r 所管理的对象替换被管理对象。

1) 等效于调用 reset(r.release()) 。

2) 等效于调用 reset(r.release()) 。 Y* 必须可隐式转换为 T* 。

3) 等效于调用 reset(m.release()) 。 auto_ptr_ref 是保有到 auto_ptr 引用的实现定义类型。 std::auto_ptr 可隐式转换到及转换自此类型。允许实现以不同的名称提供该模板,或以其他方式实现等价的功能。

参数

r-另一 auto_ptr ,从它转移对象的所有权
m-保有到 auto_ptr 引用的实现定义类型对象

返回值

*this 。

转换被管理指针到指向另一类型的指针

std::auto_ptr<T>::operator auto_ptr<Y>

template< class Y >
operator auto_ptr_ref<Y>() throw();

(1)(C++11 中弃用)
(C++17 中移除)

template< class Y >
operator auto_ptr<Y>() throw();

(2)(C++11 中弃用)
(C++17 中移除)

转换 *this 为对于相异类型 Yauto_ptr

1) 返回保有到 *this 引用的实现定义类型对象。 std::auto_ptr 可转换并且可赋值自此模板。允许实现以不同的名称提供该模板,或以其他方式实现等价的功能。

2) 以调用 release() 获得的指针构造新的 auto_ptr

参数

(无)

返回值

1) 保有到 *this 的引用的实现定义类型对象。

2) 拥有由调用 release() 获得的指针的 auto_ptr

返回指向被管理对象的指针

std::auto_ptr<T>::get

T* get() const throw();

(C++11 中弃用)
(C++17 中移除)

返回 *this 所保有的指针。

参数

(无)

返回值

*this 所保有的指针。

访问被管理对象

std::auto_ptr<T>::operator*, 
std::auto_ptr<T>::operator->

T& operator*() const throw();

(1)(C++11 中弃用)
(C++17 中移除)

T* operator->() const throw();

(2)(C++11 中弃用)
(C++17 中移除)

解引用指向被管理对象的指针。第一版本要求 get() != 0 。

参数

(无)

返回值

1) *get() 。

2) get() 。

替换被管理对象

std::auto_ptr<T>::reset

void reset( T* p = 0 ) throw();

(C++11 中弃用)
(C++17 中移除)

替换 p 为保有的指针。若当前实现保有的指针不是空指针,则调用 delete get() 。

参数

p-指向待管理对象的指针

返回值

(无)

释放被管理对象的所有权

std::auto_ptr<T>::release

T* release() throw();

(C++11 中弃用)
(C++17 中移除)

返回保有的指针。调用后 *this 保有空指针。

参数

(无)

返回值

get() 。

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++智能指针 智能指针_unique_ptr智能指针详解 智能指针详解 作为智能指针的⼀种,unique_ptr 指针⾃然也具备"在适当时机⾃动释放堆内存空间"的能⼒。和 shared_ptr 指针最⼤的不同之处在 于,unique_ptr 指针指向的堆内存⽆法同其它 unique_ptr 共享,也就是说,每个 unique_ptr 指针都独⾃拥有对其所指堆内存空间的所有 权。 这也就意味着,每个 unique_ptr 指针指向的堆内存空间的引⽤计数,都只能为 1,⼀旦该 unique_ptr 指针放弃对所指堆内存空 间的所有权,则该空间会被⽴即释放回收。 unique_ptr 智能指针是以模板类的形式提供的,unique_ptr<T>(T 为指针所指数据的类型)定义在<memory>头⽂件,并位于 std 命名空间 中。因此,要想使⽤ unique_ptr 类型指针,程序中应⾸先包含如下 2 条语句: 1. #include <memory> 2. using namespace std; 第 2 句并不是必须的,可以不添加,则后续在使⽤ unique_ptr 指针时,必须标注std:: 。 unique_ptr智能指针的创建 智能指针的创建 考虑到不同实际场景的需要,unique_ptr<T> 模板类提供了多个实⽤的构造函数,这⾥给读者列举了⼏种常⽤的构造 unique_ptr 智能指针的⽅式。 1) 通过以下 2 种⽅式,可以创建出空的 unique_ptr 指针: 1. std::unique_ptr<int> p1(); 2. std::unique_ptr<int> p2(nullptr); 2) 创建 unique_ptr 指针的同时,也可以明确其指向。例如: 1. std::unique_ptr<int> p3(new int); 由此就创建出了⼀个 p3 智能指针,其指向的是可容纳 1 个整数的堆存储空间。 和可以⽤ make_shared<T>() 模板函数初始化 shared_ptr 指针不同,C++11 标准中并没有为 unique_ptr 类型指针添 加类似的模板函数。 3) 基于 unique_ptr 类型指针不共享各⾃拥有的堆内存,因此 C++11 标准中的 unique_ptr 模板类没有提供拷贝构造函数,只提供 了移动构造函数。例如: 1. std::unique_ptr<int> p4(new int); 2. std::unique_ptr<int> p5(p4);//错误,堆内存不共享 3. std::unique_ptr<int> p5(std::move(p4));//正确,调⽤移动构造函数 值得⼀提的是,对于调⽤移动构造函数的 p4 和 p5 来说,p5 将获取 p4 所指堆空间的所有权,⽽ p4 将变成空指针(nullptr)。 4) 默认情况下,unique_ptr 指针采⽤ std::default_delete<T> ⽅法释放堆内存。当然,我们也可以⾃定义符合实际场景的释放规 则。值得⼀提的是,和 shared_ptr 指针不同,为 unique_ptr ⾃定义释放规则,只能采⽤函数对象的⽅式。例如: 1. //⾃定义的释放规则 2. struct myDel 3. { 4. void operator()(int *p) { 5. delete p; 6. } 7. }; 8. std::unique_ptr<int, myDel> p6(new int); 9. //std::unique_ptr<int, myDel> p6(new int, myDel()); unique_ptr<T>模板类提供的成员⽅法 模板类提供的成员⽅法 为了⽅便⽤户使⽤ unique_ptr 智能指针,unique_ptr<T> 模板类还提供有⼀些实⽤的成员⽅法,它们各⾃的功能如表 1 所⽰。 表 1 unique_ptr指针可调⽤的成员函数 成员函数名 成员函数名 功 功 能 能 operator*() 获取当前 unique_ptr 指针指向的数据。 operator->() 重载 -> 号,当智能指针指向的数据类型为⾃定义的结构体时,通过 -> 运算符可以获取其内部的指定成员。 operator =() 重载了 = 赋值号,从⽽可以将 nullptr 或者⼀个右值 unique_ptr 指针直接赋值给当前同类型的 unique_ptr 指针。 operator []() 重载了 [] 运算符,当 unique_ptr 指针指向⼀个数组时,可以直接通过 [] 获取指定下标位置处的数据。 get() 获取当前 unique_ptr 指针内部包含的普通指针。 get_deleter()
C++智能指针auto_ptr详解 指针,相信⼤家并不陌⽣。⽆论是我们在进⾏查看内存还是在修改字符串,我们都会⽤到指针。 最常见的情况则是我们使⽤malloc或者new申请到了⼀块内存,然后⽤⼀个指针来保存起来。我们都知道有内存的申请那就必须要对它进⾏ 释放的处理,否则会造成最严重的后果——内存泄漏。⼀个或者两个申请的内存我们或许不会忘记去释放,但是如果成千上万⾏代码,你还 能记得住哪个释放了哪个没有释放吗? ⽽智能指针就是为了解决这个问题⽽产⽣的。最开始智能指针是在boost库中的,随着时间发展现在已经成为了C11的特性。(虽然我们本 篇要介绍的最基础的auto_ptrC++11中已经被unique_ptr替代了。。) 智能指针的基本原理 智能指针其实是⼀个类,可以通过将普通指针作为参数传⼊智能指针的构造函数实现绑定。只不过通过运算符重载让它"假装"是⼀个指 针,也可以进⾏解引⽤等操作。既然智能指针是⼀个类,对象都存在于栈上,那么创建出来的对象在出作⽤域的时候(函数或者程序结束)会 ⾃⼰消亡,所以在这个类中的析构函数中写上delete就可以完成智能的内存回收。 Auto_ptr详解 使⽤时,需要包含头⽂件:memory。 auto_ptr,作为智能指针的始祖,能基本实现我们所期望的功能。⽽且设计简单源码易懂,虽然缺陷众多,但作为了解智能指针的研究对象 还是⼗分合适的。 ⾸先我们先来写⼀个测试类⽤于分析。 #include <iostream> #include <memory> using namespace std; class Test { public: Test(int param = 0) //调⽤时,可以指定是第⼏个对象。默认第0个 { num = param; cout << "Simple:" << num << endl; } ~Test() //析构时会指出第⼏个对象被析构。 { cout << "~Simple:" << num << endl; } void PrintSomething() //输出附加的字符串⽅法。 { cout << "PrintSomething:" << info_extend.c_str() << endl; } int num; //代表这个对象的序号。 string info_extend; //附加的字符串。 }; 接下来,我们通过⼏个测试函数来实验⼀下auto_ptr的基本功能,再来了解⼀下它的弊端。 I.Auto_ptr的基本功能 的基本功能 void TestAutoPtr1() { auto_ptr<Test> my_auto (new Test(1)); //绑定⼀个Test类的新建对象 if(my_auto.get()) //get函数⽤来显式返回它拥有的对象指针,此处判⾮空 { my_auto->PrintSomething(); my_auto.get()->info_extend = "Addition"; //对类内成员进⾏操作 my_auto->PrintSomething(); //看是否成功操作 (*my_auto).info_extend += " other"; //实验解引⽤操作 mt_auto->PrintSomething(); } } 运⾏结果: 我们可以看到在绑定时输出Simple:1,之后也能正常实现Test类中的功能,同时my_auto可以通过get⽅法进⾏裸指针赋值以及使⽤*进⾏ 解引⽤操作,与普通指针⽆异。最后函数结束后,在调⽤析构函数的同时auto_ptr的析构函数也将Test类的对象delete掉,我加⼊的内存泄 漏探测⼯具也显⽰No memory leaks detected(没有检查测到内存泄漏). II.Auto_ptr的弊端 的弊端1 void TestAutoPtr2() { auto_ptr<Test> my_auto1 (new Test(1)); if(my_auto1.get()) { (*my_auto1).info_extend = "Test"; //先赋予⼀个初始值作为区别两个指针的标志 auto_ptr<Test> my_auto2; my_auto2 = my_auto1; my_auto2->PrintSomething(); //打印发现成功转移 my_auto1->PringSomething(); //崩溃 } } 在这个程序的最后⼀步会崩溃,罪魁祸⾸就是my_auto2 = my_auto1语句。 autp_ptr对赋值运算符重载的实现是reset(Myptr.release()),即reset和release函数的组合。release会释放所有权,reset则是⽤于接受
C++智能指针:shared_ptr⽤法详解 C++智能指针:shared_ptr⽤法详解 shared_ptrC++11⾥的新特性,其包装了new操作符在堆上分配的动态对象。如: shared_ptr<int> sp1(new int(100)); //相当于 //int *sp1=new int(100); //auto sp1=make_shared<int>(100); 它与普通指针相⽐,最⼤的不同点就是shared_ptr是⼀个类,当对象⽣命周期结束时,会⾃动调⽤其析构函数,释放内存。⽽不再需要程 序员显⽰地调⽤delete关键字。 同时,shared_ptr重载了"*"和"->"操作符以模仿原始指针的⾏为,并且提供了显⽰bool类型转换以判断指针的有效性。 shared_ptr<int> sp1(new int(100)); assert(sp1); *sp1=200; shared_ptr<string> sp2(new string("Hello")); assert(sp2->size()==5); 我们还可以使⽤shared_ptr的成员函数get()获取原始指针 shared_ptr<int> sp1(new int(100)); int *Int_ptr=sp1.get(); shared_ptr⾥的reset()函数 shared_ptr⾥有个成员函数use_count(),⽤于返回该对象的引⽤计数。 shared_ptr<int> sp1(new int(100)); cout<<"当前计数: "<<sp1.use_count()<<endl; auto sp2=sp1; cout<<"当前计数: "<<sp1.use_count()<<endl; { auto sp3=sp2; cout<<"当前计数: "<<sp1.use_count()<<endl; } cout<<"当前计数: "<<sp1.use_count()<<endl; 当⼀个shared_ptr对象调⽤reset()函数时,它的作⽤时将引⽤计数减⼀,调⽤本⾝的对象的引⽤计数变为0. shared_ptr<int> sp1(new int(100)); cout<<"当前计数: "<<sp1.use_count()<<endl; auto sp2=sp1; cout<<"当前计数: "<<sp1.use_count()<<endl; { auto sp3=sp2; cout<<"当前计数: "<<sp1.use_count()<<endl; } cout<<"当前计数: "<<sp1.use_count()<<endl; sp2.reset();//这⾥换成sp1.reset(),可以发现sp2的计数为1,sp1的计数为0. cout << "sp2当前计数: " << sp2.use_count() << endl; cout << "sp1当前计数: " << sp2.use_count() << endl; 上⾯代码运⾏后,sp2的计数为0,sp1的计数为1。若将sp2.reset()换位sp1.reset(),则sp2的计数为1,sp1的计数为0。 在每次对shared_ptr进⾏拷贝或者赋值的时候,都会使计数加1。 ⼯⼚函数 每次使⽤shared_ptr都需要显⽰的使⽤new关键字创建⼀个对象。固std库提供了⼀个⼯⼚函数make_shared()。 ⽤法: auto sp1=make_shared<int>(100); //相当于 shared_ptr<int> sp1(new int(100)); make_shared是⼀个泛型,<>⾥⾯为数据类型,()对应着new()⾥的东西,其返回值是⼀个shared_ptr类型的变量。 定制删除器 shared_ptr的构造函数可有多个参数,其中有⼀个是shared_ptr(Y *p,D d),第⼀个参数是要被管理的指针,它的含义与其构造函数的参 数相同。⽽第⼆个参数则告诉shared_ptr在析构时不要使⽤delete来操作指针p,⽽要⽤d来操作,即把delete p 换成d(p)。因此,我们 就可以⾃⼰制作⼀个删除器 如:对于传统的struct FILE的C⽂件操作,需要 FILE *fp=fopen("./1.txt","r"); //... //... fclose(fp); 若⽤shared_ptr,则可以这样做: shared_ptr<FILE> fp(fopen("./1.txt","r"), fclose); 离开作⽤域时,shared_ptr会⾃动调⽤fclose()函数关闭⽂件。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值