zoukankan      html  css  js  c++  java
  • c++11之智能指针

    由于在c++中我们可以动态分配内存,但有时候我们会忘记用

    delete或free释放内存,就会导致内存泄露。所以c++11提供了智能指针这种东西

    本文参考了知乎某知乎友的

    https://www.zhihu.com/people/mo-shan-zhe/activities

    比如下面这两种情况

    //1 内存泄漏 str1所指的资源没有被释放
    {
        string* str1 = new string("hello");
        string* str2 = new string("world");
    }
    
    //2 多重释放,引起程序崩溃
    {
        string* str1 = new string("hello");
        delete str1;
        //...
        delete str1;//引起程序崩溃
    }
    

     可能平时都写在一个文件不会忘记释放内存,但如果是一个大的项目就出问题了

    然后是智能指针的赋值方式和普通指针有差异

    可以在定义时就可以动态分配内存单元,但不允许先定义智能指针,再为其动态分配内存空间

     

    再然后普通指针和智能指针之间的赋值也得很注意,

    不能把智能指针指向普通内存变量,或者把非智能指针赋值给智能指针。

    但可以把智能指针赋值给普通指针,但不是那么直接,需要通过智能指针的get()成员函数获取智能指针中的指针后

    再赋值给普通指针

    1.先说一下auto_prt是c++98标准定义的独占智能指针,这意味着

    一个对象只能被一个auto_prt指向,两个同类型的auto_ptr不能指向同一个对象

    指针的赋值或复制操作会改变对象所有权,被复制的auto_prt不再指向任何对象

    #include<iostream>
    #include<memory>
    #include<string>
    using namespace std;
    
    int main()
    {
    	auto_ptr<string> p1(new string("hello world!"));
    	auto_ptr<string> p2;
    	p2 = p1;//p1不再指向任何对象,其所指对象被p2指向了
    	//cout << *p1;//错误代码,因为p1不指向任何对象 
    
    	cout << *p2 << endl; 
    	//p1 = new string("hello")不能用这种方式给智能指针赋值
    	auto_ptr<string> p3(p2); //p2不再指向任何对象,其所指对象被p3指向了
    	cout << *p3 << endl;
    	//cout << *p2 << endl;//错误代码,因为p1不指向任何对象 
    	return 0;
    }
    

      

    运行是会有警告,

    因为c++11不推荐使用auto_ptr,提出了unique_ptr来代替,用途和auto_ptr相同

    c++11禁止unique_ptr之间的赋值,也不允许使用一个unique_ptr初始化其他指针,否则会出现编译错误

    比如

    int main()
    {
    	unique_ptr<string> p1(new string("hello world!"));
    	unique_ptr<string> p2;
    	p2 = p1;//错误 
    	unique_ptr<string> p3(p1);//错误 
    	//system("pause");
    	return 0;
    }
    

      

    下面再来说shared_ptr

    它是一种共享指针,也就是说多个指针可以同时指向一个对象。

    c++11允许shared_ptr指针之间的赋值,也允许使用一个智能指针初始化其他指针

    再看原理分析

    1.当从堆上申请了一个资源时,我们就创建一个智能指针对象,使它指向这个资源,同时,

    在堆上申请一个用于计数的资源,让后来所有的指向该资源的对象都共享这个计数资源,这样,引用计数的个数就只有一份。

    2.当将ptr1对象赋值给对象ptr2时,其共享的引用计数变为2。

    3.删除ptr2对象时,其对应的引用计数减为1。

    4.删除ptr1对象时,引用计数变为0,则释放资源。

    智能指针的一种实现方式

    首先,智能指针是一个类,这样就可以使用构造函数和析构函数对引用计数进行维护;

    其次,它要表现出指针的行为,并且使用起来也要像普通指针一样;

    最后,智能指针对任何类型都可以使用,所以它应该是一个模板。

    具体实现看知乎原文吧

    我们看一个应用例子把,实现两个数交换

    #include<iostream>
    #include<memory>
    using namespace std;
    
    void swap(shared_ptr<int> a,shared_ptr<int> b)
    {
    	int t;
    	t = *a;
    	*a = *b;
    	*b = t;
    }
    
    int main()
    {
    	shared_ptr<int> p1(new int(9));
    	
    	shared_ptr<int> p2 = p1;
    	
    	shared_ptr<int> p3(new(int)),p4(new int(8)),p5;
    	
    	cout << "p1 = " << *p1 << "	p4 = " << *p4 << endl;
    	
    	swap(p1,p4);
    	
    	cout << "p1 = " << *p1 << "	p4 = " << *p4 << endl;
    	
    	p3 = p4 = p5 = p1;
    	
    	cout << *p1 << "	" << *p2 << "	" << *p3 << "	" << *p4 << "	" << *p5 << endl;
    	return 0;
    }
    

      

    上面的代码我们多次用了new动态分配内存空间,但我们并没有delete过,

    由于shared_ptr的存在,它会自动回收,就不会造成内存泄露

    同时c++11还提供了一个配合shared_ptr使用的弱智能指针weak_ptr,

    用于解决两个shared_ptr指针应用之间的循环计数问题。这个我不敢看了后面再补吧

  • 相关阅读:
    CodeForces 660D Number of Parallelograms
    【POJ 1082】 Calendar Game
    【POJ 2352】 Stars
    【POJ 2481】 Cows
    【POJ 1733】 Parity Game
    【NOI 2002】 银河英雄传说
    【NOI 2015】 程序自动分析
    【POJ 1704】 Georgia and Bob
    【HDU 2176】 取(m堆)石子游戏
    【SDOI 2016】 排列计数
  • 原文地址:https://www.cnblogs.com/mch5201314/p/11687609.html
Copyright © 2011-2022 走看看