Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a copy of vector of shared_ptrs? [duplicate]

There is vector of shared_ptr to base class.

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()));

How can I make a copy of the vector?
Pointers of the copy must point to new objects.

like image 998
Ufx Avatar asked Mar 16 '18 12:03

Ufx


People also ask

How do you copy vector vectors?

You just use its copy constructor or assignment operator: std::vector<std::vector<int> > vec; std::vector<std::vector<int> > copy_of_vec = vec; Yes, it's really that simple once you get rid of all the pointers.

How do I copy a vector array to another?

Begin Initialize a vector v1 with its elements. Declare another vector v2 and copying elements of first vector to second vector using constructor method and they are deeply copied. Print the elements of v1. Print the elements of v2.

What is a vector copy?

Copy enables you to: define a vector of operands, copy the values or bit status of each operand within that vector, write those values or status into a corresponding vector of operands of the same length.


2 Answers

Do you want deep copy of shared_ptr collection?

I will only refer to the following article.

Deep copy constructor with std::vector of smart pointers


And this is the code I just wrote.

#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;
}
like image 31
Minos Avatar answered Oct 18 '22 21:10

Minos


You should add a pure virtual member function like clone to Base. Implement it in your derived classes, then do something like this:

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

That being said, this is a bad idea. You're breaking semantics such as direct assignment of vectors and copy constructors, since they won't do what users will expect (assuming you actually need to actually make a new instance of each object).

like image 83
Stephen Newell Avatar answered Oct 18 '22 20:10

Stephen Newell