unique / shared_ptr with custom operator =

时间:2016-09-23 21:27:48

标签: c++

我正在处理多态类型(也就是说,我总是通过指针与它交互),它有方法" Destroy()"和"克隆()",我想将它包装在资源安全类型中。

现在,如果" Destroy()"是我不得不担心的,然后我可以将unique_ptr与自定义删除器一起使用,这很容易。 但是,此资源句柄类型用作另一种类型的成员,否则可使用默认生成的副本和分配操作进行复制。理想情况下,我想自定义资源句柄的复制构造函数和赋值来调用" Clone()"就像我已经自定义资源句柄的析构函数来调用&#34 ;销毁()&#34 ;.但仔细查看unique_ptr和shared_ptr上的文档,我看不到任何可以让我这样做的内容。

  1. 我是否遗漏了文档中的内容?有没有现成的标准方法来做到这一点?
  2. 如果没有,我应该扩展unique_ptr并覆盖复制操作吗?
  3. 或者,我应该从头开始用所有常用的指针语义编写自己的资源句柄吗?

2 个答案:

答案 0 :(得分:3)

您可以围绕std::unique_ptr

创建包装器
// To handle your cusstom Destroy
struct DestroyDeleter
{
     void operator(Interface* o) {
         object->Destroy();
         delete object;
     }
};

using InterfacePtr = std::unique_ptr<Interface, DestroyDeleter>;

// To handle the copy with clone:
class wrapper
{
public:
    explicit wrapper(InterfacePtr o) : data(std::move(o)) {}

    wrapper(const wrapper& rhs) : data(rhs.data->Clone()) {}
    wrapper(wrapper&& rhs) = default;

    wrapper& operator =(const wrapper& rhs) { data = rhs.data->Clone(); }
    wrapper& operator =(wrapper&& rhs) = default;

    const Interface* operator ->() const { return data.get(); }
    Interface* operator ->() { return data.get(); }

    const Interface& operator *() const { return data; }
    Interface& operator *() { return *data; }

private:
    InterfacePtr data;
};

答案 1 :(得分:0)

拥有unique_ptrshared_ptr的原因之一是复制和处理这些指针是一种廉价的操作,不涉及复制底层对象。

这就是为什么智能指针不会为您安装自己的operator=实现任何手段的原因。据我了解您的问题,当您复制智能指针时,您想要调用自定义Clone()Destroy()方法。

好吧,unique_ptrshared_ptr实施他们自己的operator=做正确的事。

对于初学者来说,Destroy()所做的任何事情都应该在你班级的析构函数中完成。这就是析构函数的用途。然后,您的clone()方法只需要克隆自己的对象,并返回一个新的unique_ptr,这样,当您已有unique_ptrshared_ptr时,使用它调用clone()方法克隆对象并返回一个指向克隆对象的智能指针:

std::unique_ptr<myClass> p;  // Or std::shared_ptr

// p is initialized, populated from there.

std::unique_ptr<myClass> new_p=p->clone();

在销毁对象之前必须调用一个独特的Destroy()方法,这是一个产生无休止的错误游行的邀请。在销毁克隆对象时忘记调用它只是时间问题。

避免在代码中创建和浪费时间的最佳方法是使它们在逻辑上不可能发生。如果需要执行某些操作来销毁对象,则需要在析构函数中完成。如果为了销毁从另一个对象克隆的对象需要做一些额外的事情,那么该对象需要有一个内部标志,指示它是一个克隆对象,并让它的析构函数根据它做正确的事情。 / p>

一旦完成,通过忘记做一些事情来摆脱克隆对象,你的代码在逻辑上就不可能搞砸了。你可以祝贺自己在将来拯救自己,浪费时间寻找一堆永远不会被创造出来的错误。你未来的自我会感谢你过去的自我。只需使用智能指针,就可以使用clone()从一开始就给你一个智能指针。