首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >多态对象数组

多态对象数组
EN

Stack Overflow用户
提问于 2018-09-07 12:32:26
回答 4查看 2.3K关注 0票数 12

我通常会发现需要创建多态对象的数组或向量。我通常更喜欢使用对基类的引用,而不是智能指针,因为它们更简单。

数组和向量被禁止包含原始引用,因此我倾向于使用指向基类的智能指针。但是,也可以选择使用std::reference_wrapperwrapper

从文档中可以看出,这就是它的预期用途之一,但是当出现包含多态对象的数组的主题时,常见的建议似乎是使用智能指针而不是std::reference_wrapper

我唯一的想法是,智能指针可以处理对象的生命周期稍微整洁一点吗?

TL:为什么在创建多态对象数组时,智能指针(如std::unique_ptr )似乎比std::reference_wrapper更可取?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-09-07 12:40:05

简单地说:

  • unique_ptr是对象的所有者。它管理拥有对象的生存期。
  • reference_wrapper在内存中包装指向对象的指针。它执行而不是来管理包装对象的生存期。

您应该创建一个unique_ptr (或shared_ptr)数组,以保证在不再需要对象时释放它。

票数 14
EN

Stack Overflow用户

发布于 2018-09-07 14:53:23

如果您有足够的主题性,可以编写一个poly_any<Base>类型。

poly_any<Base>是一个仅限于存储从Base派生的对象的any,它提供了一个向底层对象返回Base&.base()方法。

一幅非常不完整的草图:

代码语言:javascript
运行
复制
template<class Base>
struct poly_any:private std::any
{
  using std::any::reset;
  using std::any::has_value;
  using std::any::type;

  poly_any( poly_any const& ) = default;
  poly_any& operator=( poly_any const& ) = default;

  Base& base() { return get_base(*this); }
  Base const& base() const { return const_cast<Base const&>(get_base(const_cast<poly_any&>(*this))); }

  template< class ValueType,
    std::enable_if_t< /* todo */, bool > =true
  >
  poly_any( ValueType&& value ); // todo

  // TODO: sfinae on ValueType?
  template< class ValueType, class... Args >
  explicit poly_any( std::in_place_type_t<ValueType>, Args&&... args );  // todo

  // TODO: sfinae on ValueType?
  template< class ValueType, class U, class... Args >
  explicit poly_any( std::in_place_type_t<ValueType>, std::initializer_list<U> il,
          Args&&... args ); // todo

  void swap( poly_any& other ) {
    static_cast<std::any&>(*this).swap(other);
    std::swap( get_base, other.get_base );
  }

  poly_any( poly_any&& o ); // todo
  poly_any& operator=( poly_any&& o ); // todo

  template<class ValueType, class...Ts>
  std::decay_t<ValueType>& emplace( Ts&&... ); // todo
  template<class ValueType, class U, class...Ts>
  std::decay_t<ValueType>& emplace( std::initializer_list<U>, Ts&&... ); // todo
private:
  using to_base = Base&(*)(std::any&);
  to_base get_base = 0;
};

然后,您只需拦截将内容放入poly_any<Base>的所有方法,并存储一个get_base函数指针:

代码语言:javascript
运行
复制
template<class Base, class Derived>
auto any_to_base = +[](std::any& in)->Base& {
  return std::any_cast<Derived&>(in);
};

一旦您这样做了,您可以创建一个std::vector<poly_any<Base>>,它是一个值类型的向量,这些值类型是从Base派生而来的。

请注意,std::any通常使用小缓冲区优化来在内部存储小对象,并在堆上存储较大的对象。但这是一个实现细节。

票数 4
EN

Stack Overflow用户

发布于 2018-09-07 12:51:33

基本上,reference_wrapper是一个可变的引用:像引用一样,它不能是空的;但是就像指针一样,您可以在它的生命周期内为它指定指向另一个对象的引用。

但是,与指针和引用一样,reference_wrapper 不管理对象的生存期。这就是我们使用vector<uniq_ptr<>>vector<shared_ptr<>>的目的:确保正确地释放引用的对象。

从性能的角度来看,vector<reference_wrapper<T>>应该与vector<T*>一样快速和高效的内存。但是,这两个指针/引用可能会变得悬空,因为它们并不是在管理对象生存期。

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

https://stackoverflow.com/questions/52222665

复制
相关文章

相似问题

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