Deep copy constructor with std::vector of smart pointers

前端 未结 1 1829
野性不改
野性不改 2021-01-06 16:48

Let\'s say I have a class FooContainer that aggregates unique_ptr objects of type Foo

#include 
#include 

class FooContainer
{
p         


        
相关标签:
1条回答
  • 2021-01-06 17:08

    Or may be I should use shared_ptr instead of unique_ptr?

    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).

    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.

    The usual fix is to give your base class a virtual method clone:

    class Foo {
    public:
        Foo(Foo&&) = default;
        Foo& operator=(Foo&&) = default;
        virtual ~Foo() = 0;
        virtual std::unique_ptr<Foo> clone() const = 0;
    
    protected: // or public if appropriate
        Foo(const Foo&);
        Foo& operator=(const Foo&);
    };
    
    class Bar : public Foo {
    public:
        virtual std::unique_ptr<Foo> clone() const;
    };
    
    std::unique_ptr<Foo> Bar::clone() const {
        return make_unique<Bar>(*this);
    }
    

    If Foo is not abstract, it would also have an actual implementation of clone().

    FooContainer::FooContainer(const FooContainer& fc)
    {
        many.reserve(fc.many.size());
        for (auto const& fptr : fc.many)
            many.emplace_back(fptr->clone());
    }
    

    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:

    template <typename T, typename... Args>
    std::unique_ptr<T> make_unique(Args&& ... args) {
        return std::unique_ptr<T>( new T(std::forward<Args>(args)...) );
    }
    

    (Together, unique_ptr, make_unique, shared_ptr, make_shared, and vector finish the huge language improvement meaning you'll almost never need the low-level and dangerous new or delete keywords again.)

    0 讨论(0)
提交回复
热议问题