例如使用shared_ptr的?例如使用shared_ptr的?(Example to use sh

2019-05-13 06:36发布

您好我今天问了一个问题,关于如何在同一矢量阵列中插入不同类型的对象和我的这个问题是代码

 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
 } 

我想用向量所以有人写道,我应该这样做:

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();
}

但随后他和其他许多人建议我会更好地利用升压指针容器
shared_ptr 。 我花了近3小时来阅读这个话题,但文档似乎很先进的给我。 ****谁能给我一个小代码示例shared_ptr使用以及为什么他们建议使用shared_ptr 。 也有其他类型,如ptr_vectorptr_listptr_deque **

EDIT1:我读了代码示例过,其中包括:

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 );
...........
}

我不明白的语法!

Answer 1:

使用vectorshared_ptr消除泄漏内存,因为你忘了走路载体和调用的可能性delete每个元素。 让我们通过例子行由行的稍作修改的版本。

typedef boost::shared_ptr<gate> gate_ptr;

创建用于共享指针型的别名。 这避免了在从分型结果C ++语言的丑陋std::vector<boost::shared_ptr<gate> >闭合大于号之间和遗忘的空间。

    std::vector<gate_ptr> vec;

创建的空载体boost::shared_ptr<gate>对象。

    gate_ptr ptr(new ANDgate);

分配一个新的ANDgate实例,并将其存储到一个shared_ptr 。 之所以单独执行该操作是为了防止如果操作抛出可能发生的问题。 这是不可能在这个例子中。 该升压shared_ptr “最佳实践”解释为什么它是分配到一个独立的对象,而不是一个临时的最佳做法

    vec.push_back(ptr);

这在载体中创建一个新的共享指针和拷贝ptr进去。 在的内脏引用计数shared_ptr确保内部的分配对象ptr被安全地转移到载体中。

什么是不解释是,析构函数shared_ptr<gate>确保了分配的内存被删除。 这是避免了内存泄漏的位置。 析构函数std::vector<T>确保析构函数T被调用存储在矢量的每个元素。 然而,对于一个指针析构函数(如gate*不会删除你已分配的内存 。 这就是你要设法避免使用什么样shared_ptrptr_vector



Answer 2:

我补充一点,关于重要的事情之一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 ,它超出范围,上课的时候仍然需要它的对象会得到释放。



Answer 3:

学习使用智能指针是在我看来,最重要的步骤成为一个称职的C ++程序员之一。 如你所知,只要你在某些时候新的对象,你想删除它。

出现的一个问题是,有例外它可以是非常努力,以确保一个对象在所有可能的执行路径总是发布一次。

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

制作一个辅助类与确保对象总是在所有的执行路径删除一次的目的。

像这样一类的例子是:性病:: auto_ptr的

但有时你想与其他分享对象。 当没有使用它了,才应删除。

为了帮助与引用计数的策略已被开发,但你仍然需要记住AddRef和手动释放REF。 在本质上,这是同样的问题,如新/删除。

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

在加入C ++ Tr1的这个现在被添加到C ++标准以及但其命名的std :: TR1 :: shared_ptr的<>。

我建议使用标准的共享指针如果可能的话。 ptr_list,ptr_dequeue等都是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的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超出范围的存储器被自动回收。

正如我在我的团队困扰新人的行使是要求他们写自己的智能指针类。 然后,在完成后immedietly丢弃类,并不会再使用它。 希望你获取了一个智能指针引擎盖下是如何工作的重要知识。 没有什么神奇真的。



Answer 4:

升压文档提供了一个非常良好的开端例如: shared_ptr的例子 (它实际上是关于智能指针的载体)或shared_ptr的文档约翰内斯·绍布以下的答案必须解释升压智能指针相当不错: 智能指针解释

背后(作为几句话越好)ptr_vector的想法是,它处理的存储的指针背后内存释放你:让我们说你有一个指针的向量作为你的榜样。 当退出应用程序或离开,其中向量定义范围你必须照顾好自己清理(你动态分配ANDgate和 - 门),但只清除向量,因为向量存储指针不会做而不是实际的对象(它不会消灭,但它所包含的内容)。

 // 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);
}

提高:: ptr_vector <>将处理上面你 - 这意味着它会收回指针IT卖场后面的内存。



Answer 5:

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

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);

>在你的载体容器插入不同的对象类型。 而对于访问,你必须使用any_cast,其工作方式dynamic_cast的,希望它会为你的工作需要。



Answer 6:

#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 DONE



Answer 7:

不同的对象添加到同一个容器中,最好的办法是使用make_shared,矢量和基于范围循环,你将有一个不错的,干净,“可读”的代码!

typedef std::shared_ptr<gate> Ptr   
vector<Ptr> myConatiner; 
auto andGate = std::make_shared<ANDgate>();
myConatiner.push_back(andGate );
auto orGate= std::make_shared<ORgate>();
myConatiner.push_back(orGate);

for (auto& element : myConatiner)
    element->run();


文章来源: Example to use shared_ptr?