抽象类的 shared_ptr 向量到副本向量

Posted

技术标签:

【中文标题】抽象类的 shared_ptr 向量到副本向量【英文标题】:vector of shared_ptr of abstract class to vector of copys 【发布时间】:2012-09-20 14:58:31 【问题描述】:

我有一个带有共享指针的向量:

std::vector<std::shared_ptr<DescriptorsNs::Descriptor> > mDescriptorList;

现在我想要一个 getter 函数,它返回一个包含这些对象副本的向量:

void CatUpdater::getDescriptorList(std::vector<Descriptor*>& descriptorList) const

    descriptorList.clear();
    for (auto it = mDescriptorList.begin(); it != mDescriptorList.end(); it++)
    
        descriptorList.push_back(*it);
    

现在的问题是 Descriptor 是一个抽象类,当我尝试将它们添加到向量中时,它会正确声明:

/usr/include/c++/4.7/ext/new_allocator.h|110|error: cannot allocate an object of abstract type ‘DescriptorsNs::Descriptor’|

我可以通过为所有类型的派生类尝试std::dynamic_pointer_cast 来解决这个问题,但应该有更简单的方法来实现这一点。

谁能告诉我将原始对象复制到返回向量的更好方法?

【问题讨论】:

如果Descriptor 是抽象的,你怎么会有std::vector&lt;Descriptor&gt;?对于多态性,您需要拥有 std::vector&lt;Descriptor*&gt; 向量就像头文件中的那个,我给它分配了派生对象。我会用一个例子来编辑 啊,这是 C++11,所以也许我遗漏了一些在新标准中有所改变的东西...... 哦,我看错了你的评论,可能也有问题,但编译器还没有抱怨。 所以应该尝试返回std::unique_ptr 的列表。 (我不能使用原始指针) 【参考方案1】:

Descriptor 是抽象的,因此不能创建对象。

但是您可以对指向这些对象的指针进行深层复制。

要做到这一点,您的类描述符缺少 clone 虚拟方法!

将它添加到您的类并在您的派生中正确实现。

class Descriptor 
 ...
  virtual Descriptor* clone() const = 0;
;


class SomeDescriptor : public Descriptor 
 ...
  virtual Descriptor* clone() const  return new SomeDescriptor (*this); 
;

在将一个向量深拷贝到另一个向量时使用 clone():

void CatUpdater::getDescriptorList(std::vector<std::shared_ptr<DescriptorsNs::Descriptor> >& descriptorList) const

    descriptorList.clear();
    descriptorList.reserve(mDescriptorList.size());
    for (auto it = mDescriptorList.begin(); it != mDescriptorList.end(); it++)
    
        descriptorList.push_back((*it)->clone());
    

【讨论】:

【参考方案2】:

我猜测,当您使用 shared_ptrs 存储对象时,它们要么是大对象,不应该被复制,要么它们代表不应该被复制的东西的单个实例。

在这种情况下,最好只填充一个 const 指针向量,这将阻止调用者修改指向的对象。

typedef std::shared_ptr<const Descriptor> ConstSharedPtr;

void CatUpdater::getDescriptorList(
                    std::vector<ConstSharedPtr>& descriptorList
                    ) const

    descriptorList.clear();

    for (auto it = mDescriptorList.begin(); it != mDescriptorList.end(); it++)
    
        descriptorList.push_back(it);
    

【讨论】:

不能将它们设为 const,因为管理它们的对象仍然需要能够更改它们 你的意思是CatUpdater 类?那仍然是非常量shared_ptrs,它只是getDescriptorList 的调用者,他将被赋予vectorconst shared_ptrs,因此无法操纵它们。 该死的!那可能应该做我想要实现的目标 问题是,在研究这个问题时,我注意到共享指针在我的时间关键型应用程序中有相当多的开销。所以我将我的数据成员更改为唯一指针的向量(因此您的解决方案变得无效) 您是否真的分析过性能并发现是这种情况?

以上是关于抽象类的 shared_ptr 向量到副本向量的主要内容,如果未能解决你的问题,请参考以下文章

访问指向对象指针向量的指针的第一个元素?

将项目从一个向量复制到另一个向量

识别已将哪个基类 shared_ptr 传递到超类 shared_ptr 向量中

为啥我不能在 C++0x 中对 std::shared_ptr 的向量执行 std::copy?

存储 std::shared_ptr<Foo> 的向量,其中 Foo 是模板类

C++ std::array 到 shared_ptr 的向量