美文网首页
chapter-12

chapter-12

作者: 峡迩 | 来源:发表于2017-07-27 22:38 被阅读0次
    // chapter-12.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include<iostream>
    #include<string>
    #include<vector>
    #include<memory>                //包含智能指针,同时包含allocator类
    #include<new
    
    using namespace std;
    
    class Stu_InfoPtr;
    class Stu_Info
    {
    public:
        friend class Stu_InfoPtr;
        Stu_Info() :data("aabb") {};
        void push_back(const string t) { data->push_back(t); }
        void pop_back() { check(0, "Empty on Stu_Info!"); data->pop_back(); }
        string &front()const { check(0, "Empty on Stu_Info!"); return data->front(); }
        string &back()const { check(0, "Empty on Stu_Info!"); return data->back(); }
    private:
        shared_ptr<vector<string>> data = make_shared<vector<string>>();        //需要值初始化。shared_ptr创建对象需要初始化,否则类函数无法运行!
        void check(vector<string>::size_type i,const string &msg) const //自己设计容器类,需要设计check函数,保证在每步操作时检查是否越界!
        {
            if (i >= data->size())
                throw out_of_range(msg);
        }
    };
    
    class Stu_InfoPtr
    {
    public:
        Stu_InfoPtr():curr(0){}
        Stu_InfoPtr(Stu_Info &a,size_t sz=0):wptr(a.data),curr(sz){}
        string &deref() const;
        Stu_InfoPtr &incr();
    
    private:
        weak_ptr<vector<string>> wptr;
        size_t curr;
        shared_ptr<vector<string>> check(size_t i, const string &msg)const;//const成员函数,不可以修改对象,只能调用const函数!
    
    };
    shared_ptr<vector<string>> Stu_InfoPtr::check(size_t i, const string &msg) const    //将weak_ptr绑定到类中shared_ptr智能指针,通过weak_ptr判断对象是否存在,如果存在则返回其智能指针!(核查指针类)
    {
        auto ret = wptr.lock();
        if (!ret)
            throw runtime_error("unbound stu_info!");
        if (i >= ret->size())
            throw runtime_error(msg);
        return ret;
    }
    string &Stu_InfoPtr::deref()const
    {
        auto p = check(curr, "err!");
        return (*p)[curr];
    }
    Stu_InfoPtr &Stu_InfoPtr::incr()
    {
        check(curr, "err!");
        ++curr;                     //递增下标!
        return *this;
    }
    
    
    unique_ptr<int> clone_int(int p)
    {
        unique_ptr<int> ret(new int(p));
        return ret;
    }
    
    int main()
    {
    
        //shared_ptr和unique_ptr都支持的操作
        //shared_ptr<T> sp;         初始化,空智能指针!
        //unique_ptr<T> up;
        //p                         将p用作条件,若p指向对象则为true
        //*p                        解引用,得到对象
        //p->mem                    
        //p.get()                   返回p中所保存的指针!若智能指针释放了对象,则返回指针所指向的对象也就消失了!切记代码不能delete返回的指针!也不要用返回的指针初始化另一个智能指针!
        //swap(p,q)                 交换p和q的指针!
        //p.swap(q)
        //shared_ptr独占的操作
        //make_shared<T>(args)      返回shared_ptr,使用args初始化对象
        //shared_ptr<T> p(q)        p是q的拷贝,会增加q中的use_count()值,指向同一个对象!
        //p=q   
        //p.unique()                若p.use_count()为1,返回true,否则返回false
        //p.use_count()             与p共享对象的只能指针数量,主要应用于调试!(当其为0时,自动销毁对象,并释放内存)
        //如果将shared_ptr存放在一个容器中,而后不再需要全部容器,要记得用erase删除不再需要的那些元素。(加入vector,即拷贝智能指针)
        shared_ptr<int> p1 = make_shared<int>(10);
        auto p2 = make_shared<string>(3, '3');
        auto p3(p2);
        auto p4=make_shared<vector<string>>();
        p4->push_back("abc");
    
        //程序使用动态内存出于三个原因:1、程序不知道自己需要多少元素;2、程序不知道所需对象的准确类型;3、程序需要在多个对象间共享数据!
        //class Stu_Info为多个对象间共享数据,当拷贝类时,底层数据直接共享!
        Stu_Info s1;
        string tmp = "aaa";
        s1.push_back(tmp);
        Stu_Info s2;
        s2 = s1;
        cout << s2.back() << endl;
    
        //直接管理内存new和delete
        int *pi1 = new int();               //值初始化为0
        string *ps1 = new string;           //初始化为空的string
        vector<int> *pv1 = new vector<int>{ 1,2,3,4,5 };
        const int *pi2 = new const int(1024);
        const string *ps2 = new const string;
        int *pi3 = new(nothrow) int(1);     //当new不能分配内存时,将抛出bad_alloc错误。声明nothrow,则只返回空指针!
    
        delete pi3;                         //释放非new分配的内存,或多次释放相同的指针值,其行为为定义!
        delete ps2;                         //内置指针管理的动态内存被显示释放前会一直存在!
        pi3 = nullptr;
        ps2 = nullptr;                      //避免空悬指针!指针本身是对象,所以需要将它置为nullptr
    
        //shared_ptr和new结合使用,当将一个shared_ptr绑定到一个普通指针时,就不应该再使用内置指针来访问对象!
        //shared_ptr<T> p(q)                p管理内置指针q所指对象,q必须为new分配的内存,且类型一致!接管后,就不应该使用内置指针访问对应内存了!
        //shared_ptr<T> p(u)                p从unique_ptr接管对象的所有权,将u置为空!
        //shared_ptr<T> p(q,d)              d为删除器,用于当程序错误时释放自定义类型对象q(q含有直接管理的内存)。d实质为函数,定义了释放对象的行为!
        //shared_ptr<T> p(p2,d)             p2为shared_ptr的拷贝!
        //p.reset()                         若p为唯一指向其对象的shared_ptr,reset会释放此对象!若传递了内置指针q,会令p指向q,否则会将p置为空!
        //p.reset(q)
        //p.reset(q,d)
    
        auto ps_reset = make_shared<string>("abc");
        if (!ps_reset.unique())                         //若多个智能指针共享对象,则制作新拷贝,再修改对象的值!
            ps_reset.reset(new string(*ps_reset));      //reset参数必须为内置指针!
        *ps_reset += "def";
    
        //unique_ptr独享对象!其没有make_shared函数,必须使用new初始化!
        unique_ptr<int> pu1(new int(1314));
        //unique_ptr<int> pu2(pu2)              不支持拷贝和赋值!
        //unique_ptr的操作
        //unique_ptr<T> pu1
        //unique_ptr<T,D> pu2                   声明类型为D的可调用对象来释放指针!
        //unique_ptr<T,D> pu3(d)
        //u=nullptr                             释放u指向的对象,将u置为空
        //u.release()                           u放弃对指针的控制权,返回指针,并将u置为空
        //u.reset()                             释放u指向的对象,并重新指向内置指针q
        //u.reset(q)
        //u.reset(nullptr)
    
        unique_ptr<string> pus1(new string("abc"));
        unique_ptr<string> pus2(pus1.release());
        pus1.reset(pus2.release());
        cout << *pus1 << endl;
        //特列:可以传递unique_ptr参数和返回unique_ptr对象
        int i_fun_cloned = 1314;
        auto pui = clone_int(i_fun_cloned);
        cout << *pui << endl;
    
        //weak_ptr,不控制所指对象生存期的弱智能指针!
        //weak_ptr<T> w             创建空智能指针
        //weak_ptr<T> w(sp)         用shared_ptr初始化指针,或者赋值!
        //w=p
        //w.reset()                 将w置为空
        //w.use_count()             与w共享对象的shared_ptr的数量
        //w.expired()               若use_count为0,则返回true
        //w.lock()                  如果expired()为true,则返回空shared_ptr,否则返回一个指向w对象shared_ptr
        //由于对象可能不存在,所以不能使用weak_ptr直接访问对象!常用于核查指针类!
        shared_ptr<string> sps(new string("abc"));
        weak_ptr<string> wps(sps);
        if (!wps.expired())
            cout << *wps.lock() << endl;
    
        //动态数组,在类中创建动态数组需要定义拷贝、赋值、析构等函数,推荐使用容器!
        int *pia1 = new int[10];    //[]内必须为整型,可以不是常量!
        //动态数组得到的是元素类型的指针,动态数组不能调用begin()和end()来返回首尾指针!同理,也不能使用范围for!
        int *pia2 = new int[10]();
        string *pis1 = new string[3]{ "a","b" };
        unique_ptr<int[]> upa(pia1);            //不支持点和箭头运算符!
        delete[]pis1;
        upa.release();
        //shared_ptr不支持管理动态数组,如果要使用,必须自定义删除器释放内存!另外shared_ptr不支持下标运算符,同时也不支持指针算术运算。因此必须使用get获取内置指针,再来访问元素!
    
        //allocator类,支持内存分配和对象构造分离!
        allocator<string> alloc;                //可以分配string的allocator对象
        auto palloc = alloc.allocate(10);       //分配n个未初始化的string
        //标准库allocator的操作
        //allocator<T> a            创建对象
        //a.allocate(n)             分配未构造的内存!
        //a.deallocate(p,n)         释放内存!释放前必须调用destroy()。此n值必须与构造时的n值相同!
        //a.construct(p,args)       在p所指向的内存上构造对象!
        //a.destroy(p)              调用析构函数!
        auto qalloc = palloc;
        alloc.construct(qalloc++, 10, "ab");
        while (qalloc !=palloc)
        {
            alloc.destroy(--qalloc);        //只能对真正构造了元素进行destroy操作!
        }
        //allocator算法,在已分配内存位置构造元素
        //uninitiated_copy(b,e,b2)          从be范围内元素拷贝到b2
        //uninitiated_copy_n(b,n,b2)        从b指向元素开始拷贝n个元素到b2
        //uninitiated_fill(b,e,t)           在迭代器b和e间创造元素,值为t
        //uninitiated_fill_n(b,n,t)         创建n个对象
        auto palloc_cp = alloc.allocate(10);
        vector<string> v_to_alloc = { "ab","bac" };
        auto qalloc_cp = uninitialized_copy(v_to_alloc.begin(), v_to_alloc.end(), palloc_cp);   //返回构造元素之后的位置!
    
        //文本查询程序
    
    
        cout << endl;
        system("pause");
        return 0;
    }
    
    //标准库定义了2个智能指针类型来管理动态分配的对象,当一个对象应该被释放时,指向它的智能指针可以确保自动释放它!
    //c++中有new为对象分配空间,有delete接受动态对象的指针,销毁对象,释放空间!
    //为了更容易使用动态内存,新标准提供智能指针,shared_ptr允许多个指针指向同一个对象,unique_ptr则独占所指向的对象,weak_ptr是弱作用,指向shared_ptr所管理的对象!
    
    
    

    相关文章

      网友评论

          本文标题:chapter-12

          本文链接:https://www.haomeiwen.com/subject/hnbtlxtx.html