chapter-12

// chapter-12.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include
#include
#include
#include                //包含智能指针,同时包含allocator类
#includepush_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> data = make_shared>();        //需要值初始化。shared_ptr创建对象需要初始化,否则类函数无法运行!
    void check(vector::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> wptr;
    size_t curr;
    shared_ptr> check(size_t i, const string &msg)const;//const成员函数,不可以修改对象,只能调用const函数!

};
shared_ptr> 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 clone_int(int p)
{
    unique_ptr ret(new int(p));
    return ret;
}

int main()
{

    //shared_ptr和unique_ptr都支持的操作
    //shared_ptr sp;         初始化,空智能指针!
    //unique_ptr up;
    //p                         将p用作条件,若p指向对象则为true
    //*p                        解引用,得到对象
    //p->mem                    
    //p.get()                   返回p中所保存的指针!若智能指针释放了对象,则返回指针所指向的对象也就消失了!切记代码不能delete返回的指针!也不要用返回的指针初始化另一个智能指针!
    //swap(p,q)                 交换p和q的指针!
    //p.swap(q)
    //shared_ptr独占的操作
    //make_shared(args)      返回shared_ptr,使用args初始化对象
    //shared_ptr 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 p1 = make_shared(10);
    auto p2 = make_shared(3, '3');
    auto p3(p2);
    auto p4=make_shared>();
    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 *pv1 = new vector{ 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 p(q)                p管理内置指针q所指对象,q必须为new分配的内存,且类型一致!接管后,就不应该使用内置指针访问对应内存了!
    //shared_ptr p(u)                p从unique_ptr接管对象的所有权,将u置为空!
    //shared_ptr p(q,d)              d为删除器,用于当程序错误时释放自定义类型对象q(q含有直接管理的内存)。d实质为函数,定义了释放对象的行为!
    //shared_ptr 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("abc");
    if (!ps_reset.unique())                         //若多个智能指针共享对象,则制作新拷贝,再修改对象的值!
        ps_reset.reset(new string(*ps_reset));      //reset参数必须为内置指针!
    *ps_reset += "def";

    //unique_ptr独享对象!其没有make_shared函数,必须使用new初始化!
    unique_ptr pu1(new int(1314));
    //unique_ptr pu2(pu2)              不支持拷贝和赋值!
    //unique_ptr的操作
    //unique_ptr pu1
    //unique_ptr pu2                   声明类型为D的可调用对象来释放指针!
    //unique_ptr pu3(d)
    //u=nullptr                             释放u指向的对象,将u置为空
    //u.release()                           u放弃对指针的控制权,返回指针,并将u置为空
    //u.reset()                             释放u指向的对象,并重新指向内置指针q
    //u.reset(q)
    //u.reset(nullptr)

    unique_ptr pus1(new string("abc"));
    unique_ptr 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 w             创建空智能指针
    //weak_ptr 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 sps(new string("abc"));
    weak_ptr 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 upa(pia1);            //不支持点和箭头运算符!
    delete[]pis1;
    upa.release();
    //shared_ptr不支持管理动态数组,如果要使用,必须自定义删除器释放内存!另外shared_ptr不支持下标运算符,同时也不支持指针算术运算。因此必须使用get获取内置指针,再来访问元素!

    //allocator类,支持内存分配和对象构造分离!
    allocator alloc;                //可以分配string的allocator对象
    auto palloc = alloc.allocate(10);       //分配n个未初始化的string
    //标准库allocator的操作
    //allocator 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 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)