C++11-复制指向抽象类型的智能指针的构造

C++11 - Copy construction of a smart pointer pointing to abstract type?

本文关键字:智能 指针 类型 抽象类 复制 抽象 C++11-      更新时间:2023-10-16

我喜欢std::unique_ptr。它可以帮助我防止内存泄漏,这非常有用。但有一个问题:不允许复制作业和构造。

尽管这个限制为程序员的安全服务,但它也是相当有限的。如果使用复制赋值和构造来处理以std::unique_ptr为成员的类,则最终会出现问题。这就是为什么我用复制构造和赋值创建了自己的unique_ptr包装器。这是它的复制构造函数:

template<typename T, class Deleter>
PointerSmartSafe<T, Deleter>::PointerSmartSafe(PointerSmartSafe const& pointer_smart_safe_) noexcept : _m_opPointerUnique((_m_opPointerUnique == nullptr) ? new T(*_m_opPointerUnique.get()) : nullptr){
}

这是复印分配操作员:

template<typename T, class Deleter>
PointerSmartSafe<T, Deleter>& PointerSmartSafe<T, Deleter>::operator=(PointerSmartSafe const& pointer_smart_safe_) noexcept{
    _m_opPointerUnique = decltype(_m_opPointerUnique)(new T(*_m_opPointerUnique.get()));
    return *this;
}

一切都很好,直到我最终使用抽象基类作为类型(T(。我收到如下错误消息:

error: cannot allocate an object of abstract type 'AbstractBaseClass'

这让我很困惑。有变通办法吗?

但有一个问题:不允许复制作业和构造。

这不是问题。如果你发现这是一个问题,你就做错了什么。

尽管这个限制为程序员的安全服务,但它也是相当有限的。

这是有意的限制,也许你应该重新考虑你的设计。

这就是为什么我用复制构造和赋值创建了自己的unique_ptr包装器。

你想要的不是unique_ptr,那么你想要的是"克隆ptr">

这让我很困惑

它有什么令人困惑的地方?您正试图创建一个抽象基类的实例。您的代码还将对非抽象基进行切片。它本质上是不安全的。

这应该告诉你一些重要的事情:复制unique_ptr持有的对象不能一般地完成,它需要unique_ptr没有的上下文。该上下文要么来自拥有你想要复制的东西的对象(这需要拥有的对象知道对象的动态类型(,要么来自你想要复制自己的东西(可以使用虚拟函数在正确的动态类型的上下文中进行复制(

传统的解决方案是向类型中添加一个虚拟clone()成员函数,然后在可能的情况下使用它。

你可以把它合并到你的构造函数中,比如这样:

template<typename T>
  auto clone(T* t) -> decltype(t->clone())
  { return t->clone(); }
template<typename T>
  std::unique_ptr<T> clone(T* t, ...)
  { return std::unique_ptr<T>(new T(*t)); }
// ... 
_m_opPointerUnique((_m_opPointerUnique == nullptr) ? clone(_m_opPointerUnique.get()) : nullptr)