2013-03-27 105 views
1

我喜欢std :: unique_ptr。它帮助我防止内存泄漏,这非常有用。但是有一个问题:不允许复制分配和构建。C++ 11 - 复制指向抽象类型的智能指针的构造?

即使这个限制服务于程序员的安全,它也是相当有限的。如果您使用复制分配和构造将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' 

这使我困惑。有没有解决方法?

+2

当你需要copy'ing各地共享指针,你为什么不使用std :: shared_ptr的?那就是它的目的,而std :: unique_ptr不是。 – 2013-03-27 13:02:37

+0

@cli_hlt,因为然后每个副本引用同一个对象,可能不是所需的。 – 2013-03-27 13:03:05

+0

@Jonathan Wakely:的确如此。太多的开销也是。 – Helixirr 2013-03-27 13:04:07

回答

6

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

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

即使这个限制服务于程序员的安全,它也是相当有限的。

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

这就是为什么我创建了自己的包装与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) 
+0

谢谢你的回答。它看起来很有前途我会尽量利用这一点。如果你不介意,你的名字将被放入我的源代码(帮助我)。 :) – Helixirr 2013-03-27 13:18:14

+2

@Helixirr我写了一个叫'value_ptr'(它模拟指针上的值语义)。你会想实现移动和复制。 Mine检测到存在'T() - > Clone()const'和'T() - > clone()const'方法,以及免费的'Clone(T const *)'和'clone(T const *)函数,它具有一个仅对'T'有效的默认'克隆(T const *)',可以通过特性复制构建,并执行'new T(* t)'。噢,当'U'是'T'的子类,或者甚至是可复制构建的时,不要忘记支持'value_ptr = value_ptr '? – Yakk 2013-03-27 19:31:23

+0

@Yakk:我已经有复制任务操作员和构造。感谢您的帮助。 – Helixirr 2013-03-27 20:09:12