寻找一个智能指针,在复制智能指针本身时将复制底层资源

时间:2016-08-01 02:58:25

标签: c++ vector smart-pointers

动机

想象一下有一个非常大的类A,我想将它存储在一个向量中,我也希望向量可以复制。因此,像std::shared_ptrstd::unique_ptr这样的智能指针不是很好的选择。我知道我可以直接在A中存储std::vector<A>的对象。但正如我所说,A是一个非常大的阶级。由于std::vector<A>的元素一直存在于内存中,因此如果我经常更新它,std::vector<A>很有可能需要重新分配内存。所以,我需要一个&#34;智能指针&#34; (让我们说copyable_ptr),它会在复制智能指针本身时复制底层资源。然后我可以使用std::vector<copyable_ptr<A>>来管理A的对象。

以下是copyable_ptr的代码段模板类:

template <typename T> class copyable_ptr {
  public:
    explicit copyable_ptr(T *p) : p(p) {}
    copyable_ptr(copyable_ptr const &rhs) : p(new T(*rhs.p)) {}
    copyable_ptr(copyable_ptr &&rhs) : p(rhs.p) { rhs.p = nullptr; }
    ~copyable_ptr() { delete p; }
    copyable_ptr &operator=(copyable_ptr rhs) {
        swap(rhs);
        return *this;
    }
    void swap(copyable_ptr &rhs) {
        using std::swap;
        swap(p, rhs.p);
    }
    T &operator*() const { return *p; }
    T *operator->() const { return &this->operator*(); }

    /* other members */

  private:
    T *p;
};

template <typename T>
inline void swap(copyable_ptr<T> &lhs, copyable_ptr<T> &rhs) {
    lhs.swap(rhs);
}

问题

是否有类似的课程我可以直接使用,或者我应该自己编写还是有其他适当的解决方案来存储容器中的大类?

修改

我想我应该更清楚地解释一下自己。 A是一个非常大的类,我想使用std::vector来管理A的对象。基本上,有四种选择可以完成这项工作:

std::vector<std::shared_ptr<A>> a1;    // #1
std::vector<std::unique_ptr<A>> a2;    // #2
std::vector<A *> a3;    // #3
std::vector<A> a4;    // #4

我不想分享A的对象,这会使#1不合适。向量将无法在#2中复制,我必须手动处理内存管理 在#3。所以,只有#4左派。

然而,我对#4感兴趣的是当a4的大小达到其容量时,重新分配发生。 a4的双倍大小将被保留(正如我所说,A是一个非常大的类,在堆中保留如此多的连续内存仅仅是为了潜在的使用是不合适的吗?)。更糟糕的是,我们可能需要将a4的每个元素从旧内存位置移动到新分配的内存中。当我提出这个问题时,我忘了提及#4的另一个落后者,那就是它不是多态支持。

因此,如果我使用std::vector<copyable_ptr<A>>来管理A的对象,我上面提到的所有问题似乎都得到了妥善处理。您所需要的只是精心设计的copyable_ptr课程,而这正是我所寻找的。

2 个答案:

答案 0 :(得分:3)

是的,有这样的事情:它本身叫做类。

智能指针的全部目的是为对象提供一个引用计数句柄,可以传递,而不复制底层对象,并在引用计数下降到0时自动销毁对象,并且引用该对象的最后一个智能指针超出范围,并且它被破坏(shared_ptrunique_ptr等之间的引用计数语义的某些变体。

如果你想要某种指向复制它的对象的指针,那么在复制指针时,你不需要指针。只需按值使用对象即可。每次复制时,您都可以保证按照定义复制对象。

周围有一些指针,绝对没有任何价值。您想直接使用该对象,在需要时复制它等等......只需使用该对象。

答案 1 :(得分:0)

据我所知,标准库中没有这样的智能指针。你的copyable_ptr似乎可以完成这项工作。我过去曾经使用过这类东西,但是对于多态类而不是真正的大类。