zoukankan      html  css  js  c++  java
  • C++ 智能指针auto_ptr、shared_ptr、unique_ptr《一》-----智能指针初识

           常规指针不具备析构函数的类对象,所以常常必须手动delete来释放内存;智能指针指向的对象,在对象过期的时候,让他的析构函数删除指向的内存。这正是auto_ptr、shared_ptr、unique_ptr背后的思想。模板auto_ptr是C++98提供的解决方案,在C++11已经将其摒弃,并提供另外两种解决方案。所以auto_ptr你不要使用就行。

         下图将说明auto_ptr 与常规指针在行为上的差别。就下图要说明的这一方面,auto_ptr、shared_ptr、unique_ptr用法相同

    以上第三步:因为要离开函数这个局部作用域,故:指针pd会被删除,如果你用 unique_ptr 指针,也会自动那个析构

    例子:

    #include<iostream>
    #include<string>
    #include<memory>
    
    class Report
    {
    public:
        Report(const std::string s):str(s)
        {
            std::cout << "对象创建" << std::endl;
        }
        ~Report()
        {
            std::cout << "对象被销毁" << std::endl;
        }
        void comment() const { std::cout << str << std::endl; }
    private:
        std::string str;
    
    };
    int main()
    {
        //这里{}作用阈问题,比如ps重复声明了3次,所以括号限制作用阈
        //参考: https://blog.csdn.net/aidem_brown/article/details/53069641
        {
            std::auto_ptr<Report> ps(new Report("using auto_ptr"));
            ps->comment();
        }
        {
            std::shared_ptr<Report> ps(new Report("using shared_ptr"));
            ps->comment();
        }
        {
            std::unique_ptr<Report> ps(new Report("using unique_ptr"));
            ps->comment();
        }
        return 0;
    }

    cmd输出:

    这三个智能指针都有一个显式 explicit构造函数,该构造函数将指针(同类型)作为参数

    //智能指针赋值操作
    using namespace std;
    shared_ptr<double> pd;
    double *p_reg = new double;
    //禁止隐式转换
    //pd = p_reg;
    //shared_ptr<double> pshared = p_reg;
    //允许显式转换
    pd = shared_ptr<double>(p_reg);
    shared_ptr<double> pshared(p_reg);

    auto_prt<string> ps (new string("hello"));
    auto_ptr<string> vocation;
    vocation = ps;

    如果ps和vocation是常规指针,两个指针将指向同一个string对象。上述代码使用是错误的,因为:程序试图删除一个对象两次;

    一次是ps过期的时候,另一次是vocation过期的时候。要避免这个问题,有如下解决方案:

    再举一例【auto_ptr错误使用】:

    #include<iostream>
    #include<string>
    #include<memory>
    
    int main()
    {
        using namespace std;
        auto_ptr<string> films[5] =
        {
            auto_ptr<string>(new string("one")),
            auto_ptr<string>(new string("two")),
            auto_ptr<string>(new string("three")),
            auto_ptr<string>(new string("four")),
            auto_ptr<string>(new string("five")),
        };
        auto_ptr<string> pwin;
        pwin = films[2];
    
        for (int i = 0; i < 5; i++)
        {
            cout <<"==" <<*films[i] << endl;
        }
        cout << "--" << *pwin << endl;//报错:auto_ptr没有解除引用      _DEBUG_ERROR("auto_ptr not dereferencable");
        return 1;
    }

    cmd输出:

    同时出现报错: _DEBUG_ERROR("auto_ptr not dereferencable");


    报错原因:
    pwin = films[2];这一句导致films[2]不再引用该字符串。在auto_ptr放弃对象的所有权后,使用

    auto_ptr<string> pwin来访问对象,当在下面for循环中,程序打印films[2]指向字符串时候,缺

    发现这是一个空指针,所以报错没有解除引用

    在上述报错的程序中,使用shared_ptr代替 auto_ptr(c++11),程序便能正常运行,如下:

    #include<iostream>
    #include<string>
    #include<memory>
    
    int main()
    {
    	using namespace std;
    	shared_ptr<string> films[5] =
    	{
    		shared_ptr<string>(new string("one")),
    		shared_ptr<string>(new string("two")),
    		shared_ptr<string>(new string("three")),
    		shared_ptr<string>(new string("four")),
    		shared_ptr<string>(new string("five")),
    	};
    	cout << "数组对象引用次数 = " <<films->use_count() << endl;
    
    	shared_ptr<string> pwin;
    	pwin = films[2];
    	cout << "数组对象引用次数 = " << pwin.use_count() << endl;
    
    	cout << "*pwin = " << *pwin << endl;
    	for (int i = 0; i < 5; i++)
    	{
    			cout << "==" << *films[i] << endl;
    	}
    	cout << "数组对象引用次数 = " << films->use_count() << endl;
    
    	pwin = nullptr;
    	cout << "数组对象引用次数 = " << pwin.use_count() << endl;
    
    	films->reset();
    	cout << "数组对象引用次数 = " << pwin.use_count() << endl;
    	return 1;
    }
    

      cmd输出如下:

     

    这次pwin和films[2]指向同一个对象,引用计数从1变成2。

  • 相关阅读:
    ajax处理返回的json数据
    (转)JavaScript Trim() IE 不支持 问题解决 .
    ajax乱码,asp,php,jsp
    常用工具软件
    给DIV添加滚动条
    java递归菜单树转换成json字符串
    将请求的数据以json(plain)输出有乱码
    json穿
    乱码问题
    getRequestURI,getRequestURL的区别
  • 原文地址:https://www.cnblogs.com/winslam/p/9070849.html
Copyright © 2011-2022 走看看