智能指针:
    为什么需要智能指针?
        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. 用vs2017对C#代码进行单元测试

    1.打开vs2017->工具->扩展与更新->联机 进行搜索Unit,截图如下: 创建C#项目: 将测试代码复制到里边,这里用到的是老师课上给的实验代码: public class ...

  2. C++ vector 比较大小

    写在前: vector 是可以直接 进行比较. vector 默认提供的   operator< 内使用了  std::lexicographical_compare  进行比较, operat ...

  3. Borg、Omega和Kubernetes:谷歌十几年来从这三个容器管理系统中得到的经验教训 原创: 韩佳瑶 译 Docker 2016-03-23Borg、Omega和Kubernetes:谷歌十几年来从这三个容器管理系统中得到的经验教训 原创: 韩佳瑶 译 Docker 2016-03-23

    Borg.Omega和Kubernetes:谷歌十几年来从这三个容器管理系统中得到的经验教训 原创: 韩佳瑶 译 Docker 2016-03-23

  4. maven报错解决

    maven-resources-plugin prior to 2.4 is not supported by m2e. Use maven-  resources-plugin versio < ...

  5. Java并发包线程池之ScheduledThreadPoolExecutor

    前言 它是一种可以安排在给定的延迟之后执行一次或周期性执行任务的ThreadPoolExecutor.因为它继承了ThreadPoolExecutor, 当然也具有处理普通Runnable.Calla ...

  6. 设计-Int(4)和Int(11)谁更美

    设计-Int(4)和Int(11)谁更美 [缘起] 大家平时在进行数据库设计的时候,如果遇到需要存储整数类型的数据的时候,通常会优先使用Int这个整数类型,在处理20亿级别的正负数值存储上,Int类型 ...

  7. office激活方式,超简单

    只需要安装个小小的程序,亲测安全可靠 详情点击下方链接 https://blog.csdn.net/weixin_40941966/article/details/80872533

  8. Java 8 Steam 例子整理

    Java 8 Steam 例子整理 kexue 关注 2016.06.06 17:44* 字数 1860 阅读 3901评论 0喜欢 6 IBM: Java 8 中的 Streams API 详解 为 ...

  9. rf笔记

    1.使用robot 用例绝对路径 可执行用例 2.robot --h 可以查看命令用法 3. 创建字典 *** Settings *** Library         Collections *** ...

  10. 123457123457#0#-----com.cym.shuXueWangGuo1--前拼后广--儿童数学

    123456123456#1#-----com.cym.shuXueWangGuo1--前拼后广--儿童数学