std::vector of objects / pointers / smart pointers to pass objects(总线错误:10)?
Posted
技术标签:
【中文标题】std::vector of objects / pointers / smart pointers to pass objects(总线错误:10)?【英文标题】:std::vector of objects / pointers / smart pointers to pass objects (buss error: 10)? 【发布时间】:2013-03-31 16:29:39 【问题描述】:我想请教一个一般性的建议。下面的代码完全编译并大致代表了我处理的代码的结构。 简而言之,我想将一系列派生自基类(Class1)的对象和一些其他参数从一个地方传递到另一个地方。更准确地说,实现父类的不同子类,收集这些子类的实例并传递参数进行处理。
问题是,您建议使用对象向量还是指针向量?我不介意从C++11
(std::unique_ptr
, std::shared_ptr
) 中寻找一些新的东西,如果这是出于某种原因更好/更安全/更少的内存泄漏/等等。如果有人可以为这种情况提供有关容器的建议和/或使用C++11
提供示例,我将不胜感激。
p/s/hereUncleBens 说,如果/当抛出异常时,使用指针可能会导致内存泄漏。所以也许我真的应该使用 智能指针 来完成这项任务?这看起来如何?
p/p/s/ 很有趣,当我尝试使用来自 std::vector< Container<d>*> / std::vector< Container<d>>
的那些 Class2
对象时,现实生活中的例子给了我 Bus error: 10。但是,我无法在简单的情况下重现错误...
#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;
【问题讨论】:
【参考方案1】:首先,Class1的析构函数应该标记为virtual,否则当派生类(例如Class2)的实例被销毁时,它的析构函数将不会被正确调用。
至于你的问题,使用对象容器的后果是:
容器可能需要复制对象,因此您需要确保有一个复制构造函数(示例中的类获取编译器生成的默认构造函数)。复制对象可能会对性能产生影响,您需要正确定义副本的语义(是深还是浅,即您是创建 class1 对象的新副本,还是仅复制引用)。 您不能有任何多态性,因此您不能将 Container 子类化,然后将基类和子类的实例放在同一个容器中。 根据容器,您的对象将在内存中是连续的(向量就是这种情况),这可以带来性能优势。如果你使用原始指针的容器,那么容器只需要复制指针(更快),你可以添加包含类型的派生实例。缺点是您必须在使用后手动销毁对象,并且正如您所提到的,这很容易泄漏内存。
shared_ptr 与原始指针有类似的优点/缺点,但关键的好处是 shared_ptr 会在不再引用它时为您销毁对象,这使得您不太可能引入内存泄漏(但它仍然当涉及异常时并非不可能这样做)。
鉴于您将这些对象移交给进一步处理,我会说基于 shared_ptr 的方法是一个不错的选择。在原始指针之上使用共享ptr的后果是:
可能存在性能开销,因为为了线程安全,大多数 shared_ptr 实现需要检查/设置锁(这可能涉及对操作系统的系统调用)。 您仍然可以通过在对象之间引入循环引用来泄漏内存。 您必须使用实现 C++11 的编译器或使用外部库(大多数人使用 boost)。使用 shared_ptrs 的示例看起来像这样(未经测试)。
#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。
【讨论】:
非常感谢您的详细回答。将修改我的真实代码以实现共享指针... 注意到您没有在答案中定义list
。我猜是std::vector
,或者可能更好boost::shared_ptr< std::vector<....>>
?
糟糕,是的,我错过了。我已经更新了添加列表声明的答案,它是共享 ptrs 的 std::vector。以上是关于std::vector of objects / pointers / smart pointers to pass objects(总线错误:10)?的主要内容,如果未能解决你的问题,请参考以下文章
std::vector of OpenCV 点,没有 push_back 方法
在基于范围的 for 循环中从 std::vector<Object> 获取指向 Object 的指针
Cpp_vector_Optimizing the usage of std::vector(vector的优化)
如何使用可用于 Swift 类的 std:vector 制作 Objective-c 类