首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::传递对象的对象/指针/智能指针的向量(总线错误: 10)?

std::传递对象的对象/指针/智能指针的向量(总线错误: 10)?
EN

Stack Overflow用户
提问于 2013-03-31 16:29:39
回答 1查看 3K关注 0票数 3

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

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

p/s/ here UncleBens说,如果/当抛出异常时,使用指针可能导致内存泄漏。所以,也许我真的应该使用智能指针来执行这个任务?这看起来怎么样?

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

代码语言:javascript
复制
#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;
 }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-31 17:29:33

首先,应该将Class1的析构函数标记为虚拟的,否则当一个派生类的实例(例如Class2)被销毁时,它的析构函数就不会被正确地调用。

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

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

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

shared_ptrs与原始指针有类似的优点/缺点,但关键的好处是,当不再引用对象时,shared_ptr会为您销毁对象,这就降低了引入内存泄漏的可能性(但在涉及异常时仍然不可能这样做)。

考虑到您将这些对象交给进一步处理,我认为基于shared_ptr的方法是一个很好的选择。在原始指针之上使用共享ptrs的后果如下:

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

使用shared_ptrs的示例看起来应该是这样的(没有测试)。

代码语言:javascript
复制
#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。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15731670

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档