具有智能指针的std :: vector的深度复制构造函数 [英] Deep copy constructor with std::vector of smart pointers

查看:410
本文介绍了具有智能指针的std :: vector的深度复制构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个FooContainer类,该类聚集了Foo类型的unique_ptr对象。

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;

}

将尝试复制指针,并且(非常感谢)编译器不允许使用unique_ptr。所以我需要做这样的事情

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
}

这是这样做的方法吗?还是我应该使用shared_ptr而不是unique_ptr?

Is this the way to do it? Or may be I should use shared_ptr instead of unique_ptr?

我还有一个附加的问题。

选择智能指针的原因(还有在上面的代码中受保护)是我派生了类BarContainer,该类聚合了许多对象Bar,而对象又是Foo的子类。由于Bar的处理与Foo非常相似,因此与两个单独的类相比,此方法可以节省很多重复的代码。

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.

但是。 BarContainer的副本构造函数有问题。它将调用FooContainer的调用复制构造函数,该函数将变旧并且仅复制Foo部分而不是整个Bar。更糟糕的是,对Bar虚拟方法的任何调用都会调用Foo的版本。
因此,我需要一种方法来覆盖此行为。无法将副本构造函数虚拟化。
而且Bar的复制构造函数可以丢弃Foo复制构造函数的结果并执行正确的复制,但这效率很低

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?

推荐答案


还是我应该使用shared_ptr而不是unique_ptr?

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


但是。 BarContainer的副本构造函数有问题。它将使用FooContainer的调用副本构造函数,它将变旧并仅复制Foo部分而不是整个Bar。

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.

通常的解决方法是给基类一个虚拟方法 clone

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

如果 Foo 是不是抽象的,它也将具有 clone()的实际实现。

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

我使用了模板函数 make_unique ,这是C ++ 11标准意外遗忘的,但很快就会正式发布。如果您的编译器没有一个,则很简单地将您自己的文件放在某个头文件中:

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

(一起, unique_ptr make_unique shared_ptr make_shared vector 完成了巨大的语言改进,这意味着您几乎永远不需要低级且危险的 new 再次删除关键字。)

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

这篇关于具有智能指针的std :: vector的深度复制构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆