如何制作shared_ptrs的矢量副本?

时间:2018-03-16 12:44:37

标签: c++ c++11 inheritance shared-ptr

基类的vector shared_ptr

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的副本? 副本的指针必须指向新对象。

3 个答案:

答案 0 :(得分:2)

您想要shared_ptr集合的深层副本吗?

我只会参考以下文章。

Deep copy constructor with std::vector of smart pointers

这是我刚写的代码。

#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;
}

答案 1 :(得分:2)

您应该向virtual添加纯clone成员函数,例如Base。在派生的class es中实现它,然后执行以下操作:

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和复制构造函数,因为它们不会执行用户期望的操作(假设您实际上需要实际创建每个对象的新实例)。

答案 2 :(得分:0)

只需复制即可。

auto v2 = v;

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