[C++11]_[初级]_[shared_ptr的使用场景]
2016-02-25 16:05
579 查看
场景
C++11之前,使用auto_ptr只能适用于 new 出来的对象,为此我还专门创建了一些工具类来释放对象.使用智能指针的方式释放malloc出来的堆空间,C++11出现后可以使用shared_ptr来管理C指针了.多线程程序经常会遇到在某个线程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() = 1 Shared ownership between 3 threads and released ownership from main: p.get() = 0x323f8, p.use_count() = 4 local pointer in a thread: lp.get() = 0x323f8, lp.use_count() = 5 local pointer in a thread: lp.get() = 0x323f8, lp.use_count() = 5 local pointer in a thread: lp.get() = 0x323f8, lp.use_count() = 3 All threads completed, the last one deleted Derived Derived::~Derived() Base::~Base()
相关文章推荐
- [C++11]_[初级]_[shared_ptr的简单使用]
- C++ 拆分字符串
- C++设计模式之工厂模式
- 面试题六 C/C++面试秘笈 之约瑟夫问题的解答--程序员面试题
- C++的运算符重载
- c++模板元编程
- 面试题五 C/C++面试秘笈 之链表的正向排序--程序员面试题
- 请问在VC++2010中如何连接用Access2010创建好的accdb数据库?
- [c++]string中删除相同字符
- C语言 链表的使用(链表的增删查改,链表逆转,链表排序)
- C++ template —— tuple(十三)
- 面试题四 C/C++面试秘笈 之判断链表是否存在环形链表问题-程序员面试题
- c++服务端用webservices【gsoap】做服务端与java后台对接信息的测试工具
- C++虚继承的概念
- 面试题三 C/C++面试秘笈 查找单链表的中间元素 --程序员面试题
- c语言入门之项目4.3——利用for循环求1-1/2*2+1/2*2*2...-1/2*2*2*2到2的8次方
- winodws平台C++共享内存实现
- C++基础知识易错点总结(2)
- C语言知识整理(二)
- [C++]智能指针