首页 > 代码库 > 【足迹C++primer】39、动态内存与智能指针(3)

【足迹C++primer】39、动态内存与智能指针(3)

动态内存与智能指针(3)
/**
* 功能:动态内存与智能指针
* 时间:2014年7月8日15:33:58
* 作者:cutter_point
*/


#include<iostream>
#include<vector>
#include<memory>
#include<string>

using namespace std;
/**
智能指针和异常
*/
void f()
{
    shared_ptr<int> sp(new int(42));        //分配一个新对象
    //这段代码抛出一个异常,且在f中未被捕获
}//在函数结束时shared_ptr自动释放内存

/*
函数退出有两种可能,正常处理结束或者发生了异常,无论哪种情况,局部对象都会被销毁
*/

//当发生异常的时候,我们直接管理的内存是不会直接释放的
void fun1()
{
    int *ip=new int(42);        //动态分配一个新对象
    //这段代码抛出一个异常,且在fun1中未被捕获
    delete ip;      //在退出之前释放内存
}

/**
智能指针和哑类
*/
struct destination{};     //表示我们正在连接什么;
struct connection{};      //使用连接所需的信息;
connection connect(destination*){}   //打开连接
void disconnect(connection){}        //关闭给定的链接
void f(destination &d/* 其他参数 */)
{
    //获得一个链接;记住使用完后要关闭它
    connection c=connect(&d);
    //使用连接
    //如果我们在f退出前忘记调用disconnect,就无法关闭c了
}

/**
使用我们自己的释放操作
*/
void end_connection(connection *p){disconnect(*p);}

void fun2(destination &d/* 其他参数 */)
{
    connection c=connect(&d);
    shared_ptr<connection> p(&c, end_connection);
    //使用连接
    //当fun2退出的时候(即使是由于异常退出),connection会被正确关闭
}

/**
unique_ptr
*/
//初始化unique_ptr必须采用直接初始化形式
//由于一个unique_ptr拥有它指向的对象,因此unique_ptr不支持普通的拷贝或赋值操作
void fun3()
{
    unique_ptr<string> p1(new string("Stegosaurus"));
//    unique_ptr<string> p2(p1);  //错误:unique_ptr不支持拷贝
    unique_ptr<string> p3;
//    p3=p2;                      //错误:unique_ptr不支持赋值
}

void fun4()
{
    unique_ptr<string> p1(new string("Stegosaurus"));
//    unique_ptr<string> p2(p1);  //错误:unique_ptr不支持拷贝
//    unique_ptr<string> p3;
//    p3=p2;                      //错误:unique_ptr不支持赋值
    //将所有权从p1(指向string Stegosaurus)转移给p2

    unique_ptr<string> p2(p1.release());    //release将p1置为空
    unique_ptr<string> p3(new string("Text"));
    //将所有权从p3转移到p2
    p2.reset(p3.release()); //reset释放了p2原来指向的内存
}

/**
传递unique_ptr参数和返回unique_ptr
*/
//返回一个unique_ptr
unique_ptr<int> clone(int p)
{
    //正确:从int*创建一个unique_ptr<int>
    return unique_ptr<int>(new int(p));
}

//返回一个局部对象拷贝
unique_ptr<int> fun5(int p)
{
    unique_ptr<int> ret(new int(p));
    //...
    return ret;
}

/**
向unique_ptr传递删除器
*/

/*
void fun6()
{
    //p指向一个类型为objT的对象,并使用一个类型为delT的对象释放objT对象
    //他会调用一个fcn的delT类型对象
    using objT=int;
    using delT=int;
    delT fcn;
    unique_ptr<objT, delT> p(new objT,fcn);
}
有问题!!!!应该用lambda
*/


/*
void fun7(destination &d /* 其他参数//* )
{
    connection *pc;
    connection c=connect(&d);       //打开连接
    //当p被销毁时候,连接将会关闭
    unique_ptr<connection, decltype(end_connection)*)
    p(&c, end_connection);
    //使用连接
    //当fun7退出时,即使是异常退出,连接也会正常关闭
}
*/
/**
weak_ptr
*/
//weak_ptr是一种不控制所指向对象生存期的智能指针,它指向一个shared_ptr
//管理的对象
//当我们创建一个weak_ptr时,要用一个shared_ptr来初始化它
void fun8()
{
    auto p=make_shared<int>(42);
    weak_ptr<int> wp(p);    //wp弱共享p;p的引用计数未改变
/*
由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock.
lock返回一个指向共享对象的shared_ptr.
*/
    if(shared_ptr<int> np=wp.lock())
    {
        //如果np不为空则条件成立
        //if中,np与p共享对象
    }
}

/**
核查指针类
*/
/*
通过使用weak_ptr,不会影响一个给定的StrBlob所指向的vector的生存期。
但是,可以阻止用户访问一个不再存在的vector的企图
*/
//对于访问一个不存在的元素的尝试,StrBlobPtr抛出一个异常
class StrBlobPtr
{
public:
    StrBlobPtr():curr(0) {}
    StrBlobPtr(StrBlob &a, size_t sz=0):wptr(a.data),curr(sz){}
    string& deref() const;
    StrBlobPtr &incr();     //前缀递增
private:
    //若检查成功,check返回一个指向vector的shared_ptr
    shared_ptr<vector<string>> check(size_t, const string&) const;
    //保存一个weak_ptr, 意味着底层vector可能会被销毁
    weak_ptr<vector<string>> wptr;
    size_t curr;    //在数组中的当前位置
};


int main()
{

    return 0;
}

PS:不要问我,为什么要这样写,因为我基本吧要写的都写到里面去了,可以看出我是先打好草稿再往上传的,但是有个问题这节确实是有点乱,好多我搞半天就是实现不了,上网查别人也是这样写,但我就是不能搞出来,我不知道是哪根筋没跳对- -,总之先看过再说,以后回头再看的时候应该会知道吧,其实现在看到从前写的那些觉得比较难的,现在看来似乎没那么难了,基本现在很轻松就可以搞出来,我是不是有点小进步呢!!大笑