智能指针:
    为什么需要智能指针?
        1. malloc出来的空间,没有进行释放,存在内存泄漏的问题。 
        2. 异常安全问题。如果在malloc和free之间如果存在抛异常,那么还是有内存泄漏。这种问题就叫异常安 全。
    RAII:
        是一种利用对象生命周期来控制程序资源(如内存,文件句柄,网络连接,互斥俩个等等)的简单技术
        优点:
            1.不需要显示地释放资源
            2.采用这种方式,对象所需地资源在其生命周期内始终保持有效

// 使用RAII思想设计的SmartPtr类
template<class T>
class SmartPtr {
public:
SmartPtr(T* ptr = nullptr)
: _ptr(ptr)
{} ~SmartPtr() {
if(_ptr)
delete _ptr;
}
private:
T* _ptr;
}; void MergeSort(int* a, int n) {
int* tmp = (int*)malloc(sizeof(int)*n);
// 讲tmp指针委托给了sp对象,用时老师的话说给tmp指针找了一个可怕的女朋友!天天管着你,直到你go die^^
SmartPtr<int> sp(tmp);
// _MergeSort(a, 0, n - 1, tmp);
// 这里假设处理了一些其他逻辑
vector<int> v(, );
// ...
} int main() {
try {
int a[] = { , , , , };
MergeSort(a, );
}
catch(const exception& e) {
cout<<e.what()<<endl;
}
return ;
}
    智能指针原理:
        需要具备指针地行为,可以解引用,也可以通过->去访问所指空间中地内容,因此还需要将*, ->,重载

template<class T>
class SmartPtr {
public:
SmartPtr(T* ptr = nullptr)
: _ptr(ptr)
{}
~SmartPtr() {
if(_ptr)
delete _ptr;
}
T& operator*() {return *_ptr;}
T* operator->() {return _ptr;}
private
T* _ptr;
};
struct Date {
int _year;
int _month;
int _day;
};
int main() {
SmartPtr<int> sp1(new int);
*sp1 =
cout<<*sp1<<endl; SmartPtr<int> sparray(new Date);
// 需要注意的是这里应该是sparray.operator->()->_year = 2018;
// 本来应该是sparray->->_year这里语法上为了可读性,省略了一个->
sparray->_year = ;
sparray->_month = ;
sparray->_day = ;
}
总结智能指针的原理:
    1.RAII特性
    2.重载opreator* 和operator->,具有像指针一样的行为
 
C++11和boost中智能指针的关系
  1. C++98中产生了第一个智能指针auto_ptr
  2. C++boost给出了更实用的scoped_ptr和shared_ptr和weak_ptr
  3. C++11,引入了unique_ptr和share_ptr和weak_ptr.需要注意的是unique_ptr对应boost的scoped_ptr.并且这些智能指针是实现原理是参考boost中的实现的
auto_ptr {

构造->保存指针信息
析构->释放指针空间 auto_ptr<int> ptr(ptr2);
拷贝构造->(转移管理权的形式,将ptr2赋值给_ptr,置空ptr2) auto_ptr<int> ptr = ptr2;
赋值运算符重载->(转移管理权,判断是否自己给自己赋值,先释放自己所指向的空间,在用ptr2赋值给_ptr,置空ptr2) }
unique_ptr {
//线程安全 //不支持拷贝构造
C++:
unique_ptr(const unique+ptr<T>& ap) = delete;
unique_ptr<T>& opreator=(const unique_ptr<T>& ap) = delete; C++:
//只声明,不实现,声明成私有 }
shared_ptr {
//会存在引用计数的线程安全问题 //实现了引用计数的方式 ////////////////////////////////////////////////////////////////////////////////////
//此方法存在一定问题
private:
T* _ptr
statice int _count;
//使用statice会存在一定问题:
//使用了statice后每个对象只会公用一块空间,而当需要多块空间来计数的时候就不能实现
//sp1; sp2(sp1)-> 1和2公用一个空间 sp3; sp4(sp3);->3和4公用一块空间
//这样就需要两个引用计数,但是statice后一个类只能存在一个引用计数
//////////////////////////////////////////////////////////////////////////////////// public:
shared_ptr(T* ptr)
:_ptr(ptr)
,_pcount(new int())
{} shared_ptr(const shared_ptr<T>& sp)
:_ptr(sp._ptr)
,_pcount(sp._pcount)
{
(*_pcount)++;
} shared_ptr<T>& operator=(const shared_ptr<T>& sp)
{
if(this != &sp)
{
//ptr1; ptr2(ptr1)
//ptr3; ptr3 = ptr2;
//先判断ptr2的计数是否为0,不为0则不能释放,说明其他指针还在使用
if(--(*_pcount) == )
{
delete _pcount;
delete _ptr;
}
_ptr = sp._ptr;
_pcount = sp._pcount;
(*_pcount)++;
}
return *this;
} ~shared_ptr()
{
if(--(*_pcount) == )
{
delete _ptr;
delete _pcount;
_pcount = nullptr;
_ptr = nullptr;
}
} private:
T* _ptr;
int* _pcount;
//_pcount 在堆上,会存在线程安全问题
}
//shared_ptr 修改确保shared_ptr的线程安全问题

shared_ptr {

public:
shared_ptr(T* ptr)
:_ptr(ptr)
,_pcount(new int())
{} shared_ptr(const shared_ptr<T>& sp)
:_ptr(sp._ptr)
,_pcount(sp._pcount)
{
(*_pcount)++;
} shared_ptr<T>& operator=(const shared_ptr<T>& sp)
{
if(this != &sp)
{
//ptr1; ptr2(ptr1)
//ptr3; ptr3 = ptr2;
//先判断ptr2的计数是否为0,不为0则不能释放,说明其他指针还是只用
if(--(*_pcount) == )
{
delete _pcount;
delete _ptr;
}
_ptr = sp._ptr;
_pcount = sp._pcount;
(*_pcount)++;
}
return *this;
} ~shared_ptr()
{
if(--(*_pcount) == )
{
delete _ptr;
delete _pcount;
_pcount = nullptr;
_ptr = nullptr;
}
} private:
T* _ptr;
int* _pcount;
//_pcount 在堆上,会存在线程安全问题
} struct Date{
int _year;
int _month;
int _day;
};
shared_ptr 的循环引用问题:
    在链表的情况:
struct ListNode{
//ListNode* _next;
//ListNode* _prev;
/*
std::shared_ptr<ListNode> _next;
std::shared_ptr<ListNode> _prev;
*/ std::weak_ptr<ListNode> _next;
std::weak_ptr<ListNode> _prev; ~ListNode()
{
cout << "~ListNode()" << endl;
}
}; int main()
{
std::shared_ptr<ListNode> node1(new ListNode);
std::shared_ptr<ListNode> node2(new ListNode);
cout << node1.use_count() << endl;
cout << node2.use_count() << endl; node1->_next = node2;
node2->_prev = node1; cout << node1.use_count() << endl;
cout << node2.use_count() << endl; return ;
}
        week_ptr——>为了解决shared_ptr产生的循环引用,它并不是RAII思想
            特点:
                1.不会增加引用计数
                2.只可以接收shared_ptr赋值给它
                3.本质并不是一个智能指针

C++新特性---智能指针的更多相关文章

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

    动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极为困难的.有时我们会忘记释放内存产生内存泄漏,有时提前释放了内存,再使用指针去引用内存就会报错. 为了更容易(同时也更安全)地使用动态内存, ...

  2. c++11新特性实战(二):智能指针

    c++11添加了新的智能指针,unique_ptr.shared_ptr和weak_ptr,同时也将auto_ptr置为废弃(deprecated). 但是在实际的使用过程中,很多人都会有这样的问题: ...

  3. C++ template的一些高级用法(元编码,可变参数,仿函数,using使用方法,. C++ 智能指针)

    1 .  通用函数可变参数模板 对于有些时候,我们无法确切的知道,函数的参数个数时,而又不想过多的使用所谓的函数重载,那么就可以效仿下面的例子: #include<iostream> #i ...

  4. [转]C++智能指针的创建

    zero 坐在餐桌前,机械的重复“夹菜 -> 咀嚼 -> 吞咽”的动作序列,脸上用无形的大字写着:我心不在焉.在他的对面坐着 Solmyr ,慢条斯理的吃着他那份午餐,维持着他一贯很有修养 ...

  5. c++ 智能指针【转载】

    zero 坐在餐桌前,机械的重复“夹菜 -> 咀嚼 -> 吞咽”的动作序列,脸上用无形的大字写着:我心不在焉.在他的对面坐着 Solmyr ,慢条斯理的吃着他那份午餐,维持着他一贯很有修养 ...

  6. 智能指针--C++

    智能指针(一):STL auto_ptr实现原理 智能指针实际上是一个类(class),里面封装了一个指针.它的用处是啥呢? 指针与内存 说到指针自然涉及到内存.我们如果是在堆栈(stack)中分配了 ...

  7. 转:c++ 11 新特性

    声 明:本文源自 Danny Kalev 在 2011 年 6 月 21 日发表的<The Biggest Changes in C++11(and Why You Should Care)&g ...

  8. C++ | 智能指针初探

    智能指针初探 在 c/c++ 语言中有一种特殊的类型--指针类型. 指针作为实体,是一个用来保存一个内存地址的计算机语言中的变量.它可以直接对内存地址中的数据进行操作,是一种非常灵活的变量.指针被誉为 ...

  9. C++11 智能指针

    C++ 11标准库引入了几种智能指针 unique_ptr shared_ptr weak_ptr C++内存管理机制是当一个变量或对象从作用域过期的时候就会从内存中将他干掉.但是如果变量只是一个指针 ...

随机推荐

  1. 常见的可以写入VIM配置文件中的设置参数

    常见的可以写入.vimrc文件中的设置参数 设置参数 含义 :set nu :set nonu 设置与取消行号 :syn on :syn off 是否依据语法显示相关的颜色帮助,在VIM修改相关的配置 ...

  2. Cesium的Property机制总结

    前言 Cesium官方教程中有一篇叫<空间数据可视化>(Visualizing Spatial Data).该文文末简单提到了Cesium的Property机制,然后话锋一转,宣告此教程的 ...

  3. layui跨域问题的解决

      跨域问题的解决 由于浏览器存在同源策略,所以如果 layui(里面含图标字体文件)所在的地址与你当前的页面地址不在同一个域下,即会出现图标跨域问题.所以要么你就把 layui 与网站放在同一服务器 ...

  4. [java]三种自定义链表排序方式

    代码: import java.util.ArrayList; import java.util.Comparator; import java.util.List; class Emp{ Strin ...

  5. Composer更新慢的终极解决方案-转

    转自:http://blog.csdn.net/fishermanmax/article/details/51975692 Packagist 镜像 请各位使用本镜像的同学注意: 本镜像已经依照 co ...

  6. Spring Boot中mybatis insert 如何获得自增id

    https://www.cnblogs.com/quan-coder/p/8728410.html 注意要显式设置主键,通过: @Options(useGeneratedKeys = true, ke ...

  7. LNMP V1.4正式版本安装及新增Let's Encrypt一键安装和其他功能

    军哥的LNMP一键安装包已经有一些年头了,着实给需要在Linux VPS.服务器中安装WEB环境的用户提供不小的帮助,而且每年儿童节都会有较大版本的更新和升级.老左在二月份的时候有体验过LNMP V1 ...

  8. spring 中常用的两种事务配置方式

    引用:http://blog.csdn.net/qh_java/article/details/51811533 引用:http://www.cnblogs.com/rushoooooo/archiv ...

  9. [转帖]为微软效力15年的微软前员工解释Windows 10为什么问题这么多

    为微软效力15年的微软前员工解释Windows 10为什么问题这么多 https://www.cnbeta.com/articles/tech/892109.htm . 测试团队已经被裁撤 . 自动化 ...

  10. PAT甲级 并查集 相关题_C++题解

    并查集 PAT (Advanced Level) Practice 并查集 相关题 <算法笔记> 重点摘要 1034 Head of a Gang (30) 1107 Social Clu ...