Let's say I have a class FooContainer that aggregates unique_ptr objects of type Foo
#include <vector>
#include <memory>
class FooContainer
{
protected:
std::vector<std::unique_ptr<Foo>> many;
//other attributes
public:
FooCoontainer(const FooContainer&);
//handling functions for Foo
};
The question is how to correctly implement deep copy constructor, and what is syntax for it. Simply assigning
FooContainer::FooContainer(const FooContainer& fc)
{
many=fc.many;
}
will attempt to copy the pointers and will be (thankfully) disallowed by the compiler for unique_ptr. so I would need to do something like this
FooContainer::FooContainer(const FooContainer& fc)
{
many.reserve(fc.many.size());
for(int i=0;i<fc.many.size();i++)
many.emplace_back(new Foo(*fc.many[i]));//assume that Foo has a copy constructor
}
Is this the way to do it? Or may be I should use shared_ptr instead of unique_ptr?
I also have an additional question.
The reason to go for smart pointers (and also for protected in the code above) is that I have derived class BarContainer that aggregates objects Bar in many, which are in turn subclass of Foo. Since the the handling of Bar is very similar to Foo this approach will allow to save a lot of duplicate code compared to two separate classes.
However,. the copy constructor of the BarContainer is problematic. It will the call copy constructor of FooContainer, that will go agead and copy only the Foo part instead of whole Bar. even worse, any invocation of the virtual methods of Bar will call the version of Foo. So I need a way to override this behaviour.Making the copy constructor virtual is not possible. Also the copy constructor of Bar could discard the result of Foo copy constructor and to dperform correct copying, but this is quite inefficient
So what is the best solution for this problem?
That depends on whether you require deep copies or are okay with shallow copies (meaning changes to one will also be visible in the other).
The usual fix is to give your base class a virtual method
clone
:If
Foo
is not abstract, it would also have an actual implementation ofclone()
.I've used a template function
make_unique
, which was accidentally forgotten from the C++11 Standard, but will be official soon. If your compiler doesn't have one, it's simple to put your own in some header file:(Together,
unique_ptr
,make_unique
,shared_ptr
,make_shared
, andvector
finish the huge language improvement meaning you'll almost never need the low-level and dangerousnew
ordelete
keywords again.)