[C++11]_[初级]_[shared_ptr的使用场景]
来源:互联网 发布:c语言产生0 9的随机数 编辑:程序博客网 时间:2024/05/01 14:20
场景
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() = 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
- [C++11]_[初级]_[shared_ptr的使用场景]
- [C++11]_[初级]_[unique_ptr的使用场景]
- [C++11]_[初级]_[weak_ptr的使用场景]
- [C/C++]_[初级]_[static_cast,reinterpret_cast,dynimic_cast的使用场景和区别]
- [C/C++11]_[初级]_[使用enumerations类型]
- [C/C++11]_[初级]_[使用std::tuple元组-固定大小的集合]
- [Java]_[初级]_[比较String和StringBuffer的区别和使用场景]
- [Cocoa]_[初级]_[NSThread的使用]
- [C/C++]_[初级]_[关于Gdiplus::Bitmap使用的注意事项]
- [C/C++标准库]_[初级]_[使用string stream]
- [Objective-c]_[块语法的使用及应用场景]
- [C/C++]_[初级]_[malloc-calloc-new的区别]
- [C/C++]_[初级]_[编程容易犯错的地方]
- [C/C++标准库]_[初级]_[std::map的使用细节]
- [C/C++标准库]_[初级]_[函数对象functor的使用]
- [C/C++标准库]_[初级]_[优先队列priority_queue的使用]
- [C/C++11]_[初级]_[使用正则表达式库regex]
- [C/C++11]_[初级]_[使用std::function来封装函数]
- ListView
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- Java发送电子邮件
- List实体集合更改任意Model中某一个字段的值,其他Model值也一起变了,引用类型和值类型的问题
- maven web项目的几种部署方式和常见的出错方式的解决
- [C++11]_[初级]_[shared_ptr的使用场景]
- CodeForces 626 A. Robot Sequence(水~)
- C/C++基础::sizeof() 与 sizeof(string)
- 文件合成器
- LeetCode 30 - Substring with Concatenation of All Words
- iOS initWithFrame:frame] 与 [UIButton buttonWithType] 对比
- 第三方框架
- 空悲切
- Android 三种跨界面的通讯方式