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指针应用之间的循环计数问题。这个我不敢看了后面再补吧

  • 相关阅读:
    PHP 标量类型与返回值类型声明
    如何使用 PHP 语言来编码和解码 JSON 对象
    mongodb的读写分离
    [FWT] UOJ #310. 【UNR #2】黎明前的巧克力
    drcom 不耍流氓
    drcom 不耍流氓
    Visual Studio 自定义项目模板
    Visual Studio 自定义项目模板
    Visual Studio 自定义项目模板
    【广告】win10 uwp 水印图床 含代码
  • 原文地址:https://www.cnblogs.com/mch5201314/p/11687609.html
Copyright © 2011-2022 走看看