如何/是否可能有一个矢量<unique_ptr<ABC>>?
How / Is it possible to have a vector<unique_ptr<ABC>>?
修改一些旧代码,在这些代码中,我手动处理指向抽象基类具体实例的原始指针向量的生命周期 class (ABC)。
所以向量的所有者有一个虚拟的 dtor,它手动检查并删除了向量的内容,等等。
由于向量的所有者拥有其中的元素,因此将其更改为 unique_ptr 的向量很有意义。
遗憾的是,这似乎是不可能的?因为 vector<unique_ptr<type>>
必须能够为 type
提供静态 dtor,但是因为在这种情况下类型是 ABC,所以它不可用,因此 vector
无法编译...
还是我遗漏了什么?
例如:
struct ABC
{
ABC() = default;
virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor
virtual std::unique_ptr<ABC> Clone() = 0;
virtual void Foo() = 0;
std::vector<std::unique_ptr<ABC>> elements;
};
EDIT2:这是一个失败的完整示例:
#include <iostream>
#include <memory>
#include <vector>
struct ABC
{
virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor
virtual std::unique_ptr<ABC> Clone() = 0;
virtual void Foo() = 0;
std::vector<std::unique_ptr<ABC>> elements;
};
struct Child : ABC
{
std::unique_ptr<ABC> Clone() override { return std::make_unique<Child>(*this); }
void Foo() override { };
};
struct Derived : Child
{
std::unique_ptr<ABC> Clone() override { return std::make_unique<Derived>(*this); }
};
int main()
{
std::unique_ptr<ABC> x;
std::unique_ptr<ABC> c = std::make_unique<Child>();
std::vector<std::unique_ptr<ABC>> elements;
elements.emplace_back(std::make_unique<Derived>());
return 0;
}
当您尝试复制 Base
的实例或从 Base
派生的类型的实例时发生错误。默认复制构造函数将尝试复制 Base::elements
,它会尝试将其每个元素复制到新的 vector
中。由于这些元素 unique_ptr<Base>
不允许复制。
这个例子重现了问题:
#include <memory>
#include <vector>
struct Base
{
using PBase = std::unique_ptr<Base>;
using VBase = std::vector<PBase>;
VBase elements;
};
int main()
{
Base x;
auto y = x; // This line causes the error
return 0;
}
您可能需要实现自己的复制构造函数和复制赋值运算符,或者通过删除这些函数来禁止复制。如果浅拷贝适用于您的应用程序,则使用 shared_ptr
可能会奏效。
为了完整起见,这是我应该做的:
class ABC
{
public:
ABC() = default;
ABC(const ABC & rhs)
{
// manually clone our elements
elements.reserve(rhs.elements.size());
for (const auto & e : rhs.elements)
elements.emplace_back(e->Clone());
}
ABC & operator = (const ABC &) = delete;
virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor
virtual std::unique_ptr<ABC> Clone() = 0;
virtual void Foo() = 0;
std::vector<std::unique_ptr<ABC>> elements;
};
修改一些旧代码,在这些代码中,我手动处理指向抽象基类具体实例的原始指针向量的生命周期 class (ABC)。
所以向量的所有者有一个虚拟的 dtor,它手动检查并删除了向量的内容,等等。
由于向量的所有者拥有其中的元素,因此将其更改为 unique_ptr 的向量很有意义。
遗憾的是,这似乎是不可能的?因为 vector<unique_ptr<type>>
必须能够为 type
提供静态 dtor,但是因为在这种情况下类型是 ABC,所以它不可用,因此 vector
无法编译...
还是我遗漏了什么?
例如:
struct ABC
{
ABC() = default;
virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor
virtual std::unique_ptr<ABC> Clone() = 0;
virtual void Foo() = 0;
std::vector<std::unique_ptr<ABC>> elements;
};
EDIT2:这是一个失败的完整示例:
#include <iostream>
#include <memory>
#include <vector>
struct ABC
{
virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor
virtual std::unique_ptr<ABC> Clone() = 0;
virtual void Foo() = 0;
std::vector<std::unique_ptr<ABC>> elements;
};
struct Child : ABC
{
std::unique_ptr<ABC> Clone() override { return std::make_unique<Child>(*this); }
void Foo() override { };
};
struct Derived : Child
{
std::unique_ptr<ABC> Clone() override { return std::make_unique<Derived>(*this); }
};
int main()
{
std::unique_ptr<ABC> x;
std::unique_ptr<ABC> c = std::make_unique<Child>();
std::vector<std::unique_ptr<ABC>> elements;
elements.emplace_back(std::make_unique<Derived>());
return 0;
}
当您尝试复制 Base
的实例或从 Base
派生的类型的实例时发生错误。默认复制构造函数将尝试复制 Base::elements
,它会尝试将其每个元素复制到新的 vector
中。由于这些元素 unique_ptr<Base>
不允许复制。
这个例子重现了问题:
#include <memory>
#include <vector>
struct Base
{
using PBase = std::unique_ptr<Base>;
using VBase = std::vector<PBase>;
VBase elements;
};
int main()
{
Base x;
auto y = x; // This line causes the error
return 0;
}
您可能需要实现自己的复制构造函数和复制赋值运算符,或者通过删除这些函数来禁止复制。如果浅拷贝适用于您的应用程序,则使用 shared_ptr
可能会奏效。
为了完整起见,这是我应该做的:
class ABC
{
public:
ABC() = default;
ABC(const ABC & rhs)
{
// manually clone our elements
elements.reserve(rhs.elements.size());
for (const auto & e : rhs.elements)
elements.emplace_back(e->Clone());
}
ABC & operator = (const ABC &) = delete;
virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor
virtual std::unique_ptr<ABC> Clone() = 0;
virtual void Foo() = 0;
std::vector<std::unique_ptr<ABC>> elements;
};