关于对象的c:std :: vector /指针/智能指针以传递对象(总线错误:10)?

std::vector of objects / pointers / smart pointers to pass objects (buss error: 10)?

我想问一个一般的建议。下面的代码可以完全编译并大致表示我要处理的代码的结构。
简而言之,我想将一系列从基类(Class1)和其他一些参数派生的对象从一个地方传递到另一个地方。更准确地说,实现父类的不同子类,收集它们的实例并传递以进行参数处理。

问题是,您是否建议使用对象向量或指针向量?我不介意从C++11(std::unique_ptrstd::shared_ptr)寻找一些新的东西,如果出于某种原因这是更好/更安全/更少的内存泄漏/等等。如果有人可以为这种情况提供容器方面的建议和/或使用C++11提供示例,我将不胜感激。

p / s /在这里UncleBens说,如果抛出异常,使用指针可能会导致内存泄漏。所以也许我真的应该为任务使用智能指针?看起来如何?

p / p / s /很有趣,现实生活中的示例给了我总线错误:10当我尝试使用std::vector< Container<d>*> / std::vector< Container<d>>中的那些Class2对象时。但是,我无法在简单的情况下重现该错误...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <string>
#include <iostream>
#include <vector>


template<int dim>
class Class1 {
   public:

     Class1() {};
    ~Class1() {};

};

template<int dim>
class Class2 : public Class1<dim>
{
   public:
     Class2() :
       Class1<dim>() {};

 };

template <int dim>
class Container
{
  public:
     Container( Class1<dim> & f, int param1) : c1(f), param_(param1) {}

  Class1<dim>  & c1;
      int param_;
 };

 static const int d = 2;

 int main()
 {
    int p = 1;
    Class2<d> c2;
    std::vector< Container<d> *> p_list;
    std::vector< Container<d> > list;
    {
      p_list.push_back ( new Container<d> ( c2,p ) );
    }
    std::cout<<"from pointers:"<<p_list[0]->param_<<std::endl;

    {
      list.push_back( Container<d> ( c2,p ) );
    }
    std::cout<<"from objects:"<<list[0].param_<<std::endl;
 }

首先,应该将Class1的析构函数标记为虚,否则,如果派生类(例如Class2)的实例被破坏,则不会正确调用它的析构函数。

对于您的问题,使用对象容器的后果是:

  • 容器可能需要制作对象的副本,因此您需要确保有一个副本构造函数(示例中的类将获取由编译器生成的默认类)。复制对象可能会对性能产生影响,因此您需要正确定义副本的语义(是深还是浅,即您是创建class1对象的新副本还是仅复制引用)。
  • 您不能具有任何多态性,因此您不能对Container进行子类化,然后将基类和子类的实例放入同一容器中。
  • 根据容器的不同,您的对象将在内存中是连续的(向量就是这种情况),这可能会带来性能上的好处。

如果您使用原始指针的容器,则该容器仅需要复制指针(更快),就可以添加包含类型的派生实例。缺点是使用后必须手动销毁对象,而且正如您提到的那样,很容易泄漏内存。

shared_ptrs与原始指针具有类似的优点/缺点,但是关键的好处是,当不再有引用时,shared_ptr会为您销毁对象,这将减少您引入内存泄漏的可能性(但是它当涉及到异常时,\\仍然不是没有可能)。

鉴于您将这些对象移交给进一步处理,我想说一个基于shared_ptr的方法是一个不错的选择。在原始指针之上使用共享ptrs的后果是:

  • 可能会有性能开销,因为为了确保线程安全,大多数shared_ptr实现都需要检查/设置锁(这可能涉及对OS的系统调用)。
  • 您仍然可以通过在对象之间引入循环引用来泄漏内存。
  • 您将必须使用实现C 11的编译器或使用外部库(大多数人使用boost)。

使用shared_ptrs的示例看起来像这样(未经测试)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <string>
#include <iostream>
#include <vector>

template<int dim>
class Class1 {
   public:
       Class1() {};
       virtual ~Class1() {};

};

template<int dim>
class Class2 : public Class1<dim>
{
    public:
        Class2() :
        Class1<dim>() {};

};

template <int dim>
class Container
{
    public:
       Container( boost::shared_ptr<Class1<dim>> f, int param1) : c1(f), param_(param1) {}

       boost::shared_ptr<Class1<dim>> c1;
       int param_;
};

static const int d = 2;

int main()
{
    int p = 1;
    boost::shared_ptr<Class1<d>> c2 = boost::make_shared<Class2<d>>();

    std::vector<boost::shared_ptr<Container<d>>> list;
    list.push_back(boost::make_shared<Container<d>>(c2,p));

    std::cout <<"from objects:" << list[0]->param_ << std::endl;
}

总而言之,如果接收容器的代码没有在任何地方存储对它们的引用,并且您不需要多态性,那么对象容器就可以了。如果有必要让接收容器的代码将它们存储在某个地方,并且/或者您想要多态容器,请使用共享的ptrs。