如何复制shared_ptrs的矢量

How to make a copy of vector of shared_ptrs?

本文关键字:ptrs shared 何复制 复制      更新时间:2023-10-16

基类有shared_ptr vector

struct Base
{
    virtual ~Base() = 0 {}
};
struct Derived1 : Base
{
};
struct Derived2 : Base
{
};
std::vector<std::shared_ptr<Base>> v;
v.push_back(std::make_shared<Base>(Derived1()));
v.push_back(std::make_shared<Base>(Derived2()));

如何复制vector
副本的指针必须指向新对象。

你应该添加一个纯virtual成员函数,如cloneBase。 在派生class中实现它,然后执行以下操作:

std::vector<std::shared_ptr<Base>> copy(std::shared_ptr<Base> const &input) {
    std::vector<std::shared_ptr<Base>> ret;
    ret.reserve(input.size());
    for(auto const &p: input) {
        ret.push_back(p->clone());
    }
    return ret;
}

话虽如此,这是一个坏主意。 你正在破坏语义,例如直接分配vector和复制构造函数,因为它们不会做用户期望的事情(假设你实际上需要为每个对象创建一个新实例(。

您想要shared_ptr收藏的深度副本吗?

我只会参考以下文章。

带有 std::智能指针矢量的深度复制构造函数


这就是我刚刚写的代码。

#include <string>
#include <memory>
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
using namespace std;
class Parent {
    string _name;
public:
    virtual shared_ptr<Parent> clone() const = 0;
    Parent(const string& name) { _name = name; }
    string getName() { return _name; }
    void setName(const string& name) { _name = name; }
};
class Child : public Parent {
public:
    Child(const string& name) : Parent(name) {}
    virtual shared_ptr<Parent> clone() const { return make_shared<Child>(*this); }
};
int main()
{
    vector<shared_ptr<Parent>> origins =
    {
        shared_ptr<Parent>(new Child("ant")),
        shared_ptr<Parent>(new Child("bee")),
        shared_ptr<Parent>(new Child("cat")),
    };
    vector<shared_ptr<Parent>> clones;
    // copy origins to clones
    transform(
        origins.begin(),
        origins.end(),
        back_inserter(clones),
        [](const shared_ptr<Parent>& ptr) -> shared_ptr<Parent> { return ptr->clone(); }
    );
    // modify values of origins
    for (const auto& origin : origins) { origin->setName(origin->getName() + "!"); }
    // print origins (modified)
    cout << "<origins>" << endl;
    for (const auto& origin : origins) { cout << origin->getName() << endl; }
    // print clones (not modified)
    cout << "<clones>" << endl;
    for (const auto& clone : clones) { cout << clone->getName() << endl; }
    return 0;
}

只需复制它。

auto v2 = v;

容器包含共享指针,因此它们在复制后会很好,并且仍然指向相同的对象,同时使它们保持活动状态。这里没有问题。