使用shared_ptr的例子?

嗨,我今天问了一个问题, 如何在同一个向量数组中插入不同types的对象 ,我的代码在这个问题是

gate* G[1000]; G[0] = new ANDgate() ; G[1] = new ORgate; //gate is a class inherited by ANDgate and ORgate classes class gate { ..... ...... virtual void Run() { //A virtual function } }; class ANDgate :public gate {..... ....... void Run() { //AND version of Run } }; class ORgate :public gate {..... ....... void Run() { //OR version of Run } }; //Running the simulator using overloading concept for(...;...;..) { G[i]->Run() ; //will run perfectly the right Run for the right Gate type } 

我想用vector,所以有人写我应该这样做:

 std::vector<gate*> G; G.push_back(new ANDgate); G.push_back(new ORgate); for(unsigned i=0;i<G.size();++i) { G[i]->Run(); } 

但随后他和其他人build议我最好使用Boost指针容器
或者shared_ptr 。 我花了最近3个小时阅读这个话题,但文件似乎相当先进。 ****任何人都可以给我一个shared_ptr用法的小代码示例,为什么他们build议使用shared_ptr 。 还有其他types,如ptr_vectorptr_listptr_deque ** **

编辑1:我也读过一个代码示例,其中包括:

 typedef boost::shared_ptr<Foo> FooPtr; ....... int main() { std::vector<FooPtr> foo_vector; ........ FooPtr foo_ptr( new Foo( 2 ) ); foo_vector.push_back( foo_ptr ); ........... } 

而我不明白的语法!

使用shared_ptr vector可以消除内存泄漏的可能性,因为您忘记了在每个元素上遍历向量并调用delete 。 让我们一行一行地稍微修改一下示例。

 typedef boost::shared_ptr<gate> gate_ptr; 

为共享指针types创build一个别名。 这样可以避免inputstd::vector<boost::shared_ptr<gate> >导致的C ++语言中的丑陋,并忘记closures大于号的间隔。

  std::vector<gate_ptr> vec; 

创buildboost::shared_ptr<gate>对象的空向量。

  gate_ptr ptr(new ANDgate); 

分配一个新的ANDgate实例并将其存储到shared_ptr 。 分开这样做的原因是为了防止操作抛出时可能发生的问题。 在这个例子中这是不可能的。 Boost shared_ptr “最佳实践”解释了为什么分配到一个独立的对象而不是暂时的最佳实践

  vec.push_back(ptr); 

这将在向量中创build一个新的共享指针,并将ptr复制到其中。 shared_ptr的内容中的引用计数确保了ptr中的分配对象被安全地转移到向量中。

没有解释的是shared_ptr<gate>的析构函数确保分配的内存被删除。 这是避免内存泄漏的地方。 std::vector<T>的析构函数确保为vector中的每个元素调用T的析构函数。 但是,指针的析构函数(例如, gate*不会删除已分配的内存 。 这就是你想通过使用shared_ptrptr_vector来避免的。

我将添加关于shared_ptr的一个重要的事情是只用以下语法构造它们:

 shared_ptr<Type>(new Type(...)); 

这样, Type的“真正”指针对你的作用域是匿名的, 只有共享指针才能保持。 因此,你不可能不小心使用这个“真正的”指针。 换句话说,永远不要这样做:

 Type* t_ptr = new Type(...); shared_ptr<Type> t_sptr ptrT(t_ptr); //t_ptr is still hanging around! Don't use it! 

虽然这会起作用,但是现在您的函数中有一个Type*指针( t_ptr ),它位于共享指针之外。 在任何地方使用t_ptr很危险的,因为你永远不知道什么时候持有它的共享指针可能会破坏它,而且会发生段错误。

其他类返回给你的指针也是一样的。 如果你没有写的类给你一个指针,把它放在shared_ptr通常是不安全的。 除非您确定课程不再使用该对象。 因为如果你把它放在一个shared_ptr ,并且超出了范围,当这个类可能还需要的时候,这个对象将被释放。

学习使用智能指针是我认为成为一个有能力的C ++程序员最重要的步骤之一。 正如你所知道的,每当你新增一个对象的时候,你想删除它。

出现的一个问题是,在例外情况下,确保一个对象总是只在所有可能的执行path中释放一次是非常困难的。

这是RAII的原因: http : //en.wikipedia.org/wiki/RAII

创build一个辅助类,目的是确保一个对象在所有执行path中总是被删除一次。

像这样的类的例子是:std :: auto_ptr

但有时你喜欢与其他人分享对象。 只有在没有人使用它时才应该删除它。

为了帮助引用计数策略已经开发出来,但是您仍然需要手动记住addref并释放ref。 本质上这是新/删除相同的问题。

这就是为什么boost已经开发boost :: shared_ptr,它是引用计数智能指针,所以你可以共享对象,而不是无意中泄漏内存。

随着C + + tr1的join,现在它被添加到c ++标准中,但是它的名字是std :: tr1 :: shared_ptr <>。

如果可能,我build议使用标准的共享指针。 ptr_list,ptr_dequeue等是指针types的IIRC专用容器。 我现在忽略他们。

所以我们可以从你的例子开始:

 std::vector<gate*> G; G.push_back(new ANDgate); G.push_back(new ORgate); for(unsigned i=0;i<G.size();++i) { G[i]->Run(); } 

这里的问题是现在每当G超出范围,我们泄漏添加到G的2个对象。让我们重写它使用std :: tr1 :: shared_ptr

 // Remember to include <memory> for shared_ptr // First do an alias for std::tr1::shared_ptr<gate> so we don't have to // type that in every place. Call it gate_ptr. This is what typedef does. typedef std::tr1::shared_ptr<gate> gate_ptr; // gate_ptr is now our "smart" pointer. So let's make a vector out of it. std::vector<gate_ptr> G; // these smart_ptrs can't be implicitly created from gate* we have to be explicit about it // gate_ptr (new ANDgate), it's a good thing: G.push_back(gate_ptr (new ANDgate)); G.push_back(gate_ptr (new ORgate)); for(unsigned i=0;i<G.size();++i) { G[i]->Run(); } 

当G超出范围时,内存自动回收。

作为一个在我的团队中困扰新人的练习,是要求他们写自己的智能指针课。 然后,你完成后立即丢弃类,不再使用它。 希望你获得关于智能指针如何工作的关键知识。 真的没有魔法

boost文档提供了一个非常好的开始示例: shared_ptr示例 (实际上是关于智能指针的向量)或shared_ptr doc Johannes Schaub的以下答案很好地解释了boost智能指针: 智能指针解释

背后的想法(尽可能less的话)ptr_vector是它为你处理存储指针背后的内存释放:假设你有一个指针向量,如你的例子。 当退出应用程序或离开定义向量的范围时,您必须自行清理(您已经dynamic分配了ANDgate和ORgate),但只是清除向量不会执行此操作,因为向量正在存储指针而不是实际的对象(它不会破坏,而是包含它)。

  // if you just do G.clear() // will clear the vector but you'll be left with 2 memory leaks ... // to properly clean the vector and the objects behind it for (std::vector<gate*>::iterator it = G.begin(); it != G.end(); it++) { delete (*it); } 

boost :: ptr_vector <>将为你处理上面的内容 – 这意味着它将释放它存储的指针后面的内存。

通过提升你可以做到这一点>

 std::vector<boost::any> vecobj; boost::shared_ptr<string> sharedString1(new string("abcdxyz!")); boost::shared_ptr<int> sharedint1(new int(10)); vecobj.push_back(sharedString1); vecobj.push_back(sharedint1); 

>用于在向量容器中插入不同的对象types。 而访问你必须使用any_cast,它像dynamic_cast一样工作,希望它可以满足你的需要。

 #include <memory> #include <iostream> class SharedMemory { public: SharedMemory(int* x):_capture(x){} int* get() { return (_capture.get()); } protected: std::shared_ptr<int> _capture; }; int main(int , char**){ SharedMemory *_obj1= new SharedMemory(new int(10)); SharedMemory *_obj2 = new SharedMemory(*_obj1); std::cout << " _obj1: " << *_obj1->get() << " _obj2: " << *_obj2->get() << std::endl; delete _obj2; std::cout << " _obj1: " << *_obj1->get() << std::endl; delete _obj1; std::cout << " done " << std::endl; } 

这是shared_ptr的一个例子。 _obj2被删除,但指针仍然有效。 输出是,./test _obj1:10 _obj2:10 _obj2:10完成