指向基类的指针的 std::vector 的深拷贝

Posted

技术标签:

【中文标题】指向基类的指针的 std::vector 的深拷贝【英文标题】:Deep copy of std::vector of pointers to a base class 【发布时间】:2018-09-18 21:42:12 【问题描述】:

我有一个std::vector<std::unique_ptr<BaseType>>。有什么干净的方法可以对vector 进行深层复制吗?

我唯一能想到的就是拥有一个使用dynamic_cast 检索派生类型的函数,然后将其复制到unique_ptr 持有的新对象中。鉴于我可以控制所有可能的派生类,这将是可行的。这有各种明显的缺点。

之前我使用了一个单一的类,它是所有派生类型的联合。在试图摆脱这种情况时,我遇到了需要复制vector的情况。

这个问题有什么好的解决办法吗?我能想出的唯一解决方案非常丑陋,甚至让我感到非常羞耻。这是尝试重构/清理我使用的代码的一大步。


vector 是必须可复制的类的成员。所以,在这种情况下,我只需要确保我可以为包含的类编写一个复制构造函数。

【问题讨论】:

一种解决方案是实现克隆模式,其中BaseType 具有virtual std::unique_ptr<BaseType> clone() = 0; 函数。每个派生类型都必须实现它以返回自己的副本。 如何制作std::unique_ptr<BaseType> 的深层副本?重复 n 次,你就知道如何复制向量了 @user463035818 如果BaseType 是多态的,深度复制std::unique_ptr<BaseType> 并不一定容易。 有什么干净的方法可以对向量进行深层复制吗? 你想在每次复制 vector 时都这样做,还是要使用明确定义的功能? @Graznarak,你当然可以做到。记得关注The Rule of Three。 【参考方案1】:

最简单的方法是实现某种形式的克隆,然后使用std::transform

#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
#include <vector>

struct base 
    // For constructors and destructors, it's business as usual.
    // Remember to implement the rule of five.
    base() std::cout << "new base\n";
    base(const base& o) 
        std::cout << "copied base\n";
    
    virtual ~base() std::cout << "destructed base\n";
    // This is the virtual copy function. We need this because only
    // the actual derived class will know how to copy itself. The
    // only way to forward this knowledge to a pointer to the base 
    // class is via a virtual function.
    // You can make this pure virtual, if you don't mind
    // the base being abstract (or if you *want* to make it 
    // abstract). It'll be safer this way.
    virtual base* copy() return new base(*this);
;

struct derived : base 
    derived() : base() std::cout << "new derived";
    derived(const derived& o) : base(o) 
        std::cout << "copied derived\n";
    
    virtual ~derived() std::cout << "destructed derived\n";
    base* copy() override return new derived(*this);
;

// example of deep copying
int main() 
    std::vector<std::unique_ptr<base>> v;
    v.emplace_back(new base());
    v.emplace_back(new derived());
    std::vector<std::unique_ptr<base>> copy_of_v;

     // The transformation merely calls copy(). Each object will be copied into
     // an instance of the correct type. 
    std::transform(v.begin(), v.end(), std::back_inserter(copy_of_v), [](auto& item)
        return std::unique_ptr<base>(item->copy());
    );

【讨论】:

以上是关于指向基类的指针的 std::vector 的深拷贝的主要内容,如果未能解决你的问题,请参考以下文章

删除指针向量时遇到问题

指向 std::vector 的指针,指针声明

c++基类对象的std::vector----派生类的运行方法

向下转换指向成员函数的指针

关于C++基类、派生类的引用和指针

指向std :: vector和std :: list元素的指针