[C++11]_[初级]_[shared_ptr的使用场景]

来源:互联网 发布:c语言产生0 9的随机数 编辑:程序博客网 时间:2024/05/01 14:20

场景

  1. C++11之前,使用auto_ptr只能适用于 new 出来的对象,为此我还专门创建了一些工具类来释放对象.使用智能指针的方式释放malloc出来的堆空间,C++11出现后可以使用shared_ptr来管理C指针了.

  2. 多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用,在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃,所以为了省时间一般都是任由这个内存泄漏发生.当然也可以经过复杂的设计,由一个监控线程来统一删除,但这样会增加代码量和复杂度.这下好了,shared_ptr 可以方便的解决问题,因为它是引用计数和线程安全的.

参考

std::shared_ptr

说明

shared_ptr的所有的方法(包括复制构造函数 和 赋值重载)都能被多线程中的不同shared_ptr实例(拥有相同的对象)安全的调用而不需要额外的同步操作.

使用

创建方式

// 方式1,使用 make_shared 支持不定参数auto sp = std::make_shared<B>(12,13);struct D{    void operator()(void* data)    {        std::cout << "free: " << (int*)data << std::endl;        free(data);    }};A* a = (A*)malloc(sizeof(A));a->i = 10;std::cout << (int*)a << std::endl;//方式2,3:外部创建指针对象传入//D 是自定义释放函数或类型std::shared_ptr<A> ar(a,D());//方法4,使用lambda作为自定义Free,就这点就比unique_ptr方便auto my_free = [](void* data){ std::cout << "hello" << std::endl; free(data);};char* buf = (char*)malloc(64);std::shared_ptr<char> p1(buf,my_free);//可以不用局部变量,直接上lambda//方式5: 复制了指针,增加引用计数std::shared_ptr<Base> lp = p;

例子0 封装到vector里

std::vector<std::shared_ptr<A>> TestSharedPtr(){    std::vector<std::shared_ptr<A>> args;    for(int i = 0; i< 400; ++i)    {        std::stringstream ss;        ss << "hello: " << i;        std::string str = ss.str();        args.push_back(std::shared_ptr<A>(new A(str)));    }    return args;}int _tmain(int argc, _TCHAR* argv[]){    auto result = TestSharedPtr();    std::vector<std::shared_ptr<A>> args(result.begin(),result.end());    for(int i = 0; i< result.size(); ++i)    {        auto& one = result[i];        std::cout << one.use_count() << ":" << one.get()->str_ << std::endl;    }    result.clear();    args.clear();    return 0;}

例子1 自定义释放函数.

struct A{    int i;};struct D{    void operator()(void* data)    {        std::cout << "free: " << (int*)data << std::endl;        free(data);    }};// 使用shared_ptr来调用特殊的释放函数.void TestCPointer(){    A* a = (A*)malloc(sizeof(A));  a->i = 10;  std::cout << (int*)a << std::endl;    std::shared_ptr<A> ar(a,D());    // 也可以这样    //std::shared_ptr<A> ar(a,free);    std::cout << ar.get()->i << std::endl;}

例子2 多线程访问

#include <iostream>#include <memory>#include <thread>#include <chrono>#include <mutex>#include <stdlib.h>#include <Windows.h>struct Base{    Base() { std::cout << "  Base::Base()\n"; }    // Note: non-virtual destructor is OK here    ~Base() { std::cout << "  Base::~Base()\n"; }};struct Derived: public Base{    Derived() { std::cout << "  Derived::Derived()\n"; }    ~Derived() { std::cout << "  Derived::~Derived()\n"; }};void thr(std::shared_ptr<Base> p){    std::this_thread::sleep_for(std::chrono::seconds(1));    std::shared_ptr<Base> lp = p; // thread-safe, even though the                                  // shared use_count is incremented    {        static std::mutex io_mutex;        std::lock_guard<std::mutex> lk(io_mutex);        std::cout << "local pointer in a thread:\n"                  << "  lp.get() = " << lp.get()                  << ", lp.use_count() = " << lp.use_count() << '\n';    }}struct A{    int i;};void Free(void* data){    std::cout << "free: " << (int*)data << std::endl;    free(data);}struct D{    void operator()(void* data)    {        std::cout << "free: " << (int*)data << std::endl;        free(data);    }};// 使用shared_ptr来调用特殊的释放函数.void TestCPointer(){    A* a = (A*)malloc(sizeof(A));    a->i = 10;    std::cout << (int*)a << std::endl;    // 自定义释放函数.    std::shared_ptr<A> ar(a,D());    // 也可以这样    //std::shared_ptr<A> ar(a,free);    std::cout << ar.get()->i << std::endl;}int main(){    std::shared_ptr<Base> p = std::make_shared<Derived>();    std::cout << "Created a shared Derived (as a pointer to Base)\n"              << "  p.get() = " << p.get()              << ", p.use_count() = " << p.use_count() << '\n';    std::thread t1(thr, p), t2(thr, p), t3(thr, p);    std::cout << "Shared ownership between 3 threads and released\n"              << "ownership from main:\n"              << "  p.get() = " << p.get()              << ", p.use_count() = " << p.use_count() << '\n';    t1.detach();    t2.detach();    t3.detach();    while(1)    {        if (p.use_count() == 1)        {            break;        }        Sleep(500);    }    std::cout << "All threads completed, the last one deleted Derived\n";    //TestCPointer();    return 0;}

输出:

Base::Base()Derived::Derived()Created a shared Derived (as a pointer to Base)p.get() = 0x323f8, p.use_count() = 1Shared ownership between 3 threads and releasedownership from main:p.get() = 0x323f8, p.use_count() = 4local pointer in a thread:lp.get() = 0x323f8, lp.use_count() = 5local pointer in a thread:lp.get() = 0x323f8, lp.use_count() = 5local pointer in a thread:lp.get() = 0x323f8, lp.use_count() = 3All threads completed, the last one deleted DerivedDerived::~Derived()Base::~Base()
0 0
原创粉丝点击