chapter-12

// 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所管理的对象!


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容