[英]Array of polymorphic unique_ptr
Using unique pointers, we can write 使用唯一指针,我们可以写
class A{};
class B: public A{};
class C: public A{};
std::vector<std::unique_ptr<A>> myArray;
//
f()
{
std::unique_ptr<B> pB {new B()};
std::unique_ptr<C> pC {new C()};
myArray.push_back(std::move(pB));
myArray.push_back(std::move(pC));
// nice! now I can use the interface of A without
// worrying about its subclasses.
}
However, if classes B
and C
need to have their own type-dependent custom deleter: 但是,如果
B
类和C
类需要拥有自己的类型相关的自定义删除器:
class A{};
class B: public A{};
class C: public A{};
template<class T>
struct custom_deleter
{ // roughly the same implementation as std::default_deleter
void operator()(T* p)
{
CustomFree(p);
}
};
//
std::vector<std::unique_ptr<A>> myArray;
//
f()
{
std::unique_ptr<B, custom_deleter<B>> pB {CustomAlloc(B())};
std::unique_ptr<C, custom_deleter<C>> pC {CustomAlloc(C())};
myArray.push_back(std::move(pB)); // error: can't convert to default deleter
myArray.push_back(std::move(pC)); // item dito
}
Is there a way to achieve what I'm trying to do here? 有没有办法实现我在这里要做的事情?
Your first example has undefined behavior because A
doesn't have a virtual
destructor. 您的第一个示例具有未定义的行为,因为
A
没有virtual
析构函数。 unique_ptr
's default deleter, std::default_delete
is stateless, so a unique_ptr<A>
will always call delete p;
unique_ptr
的默认删除器, std::default_delete
是无状态的,因此unique_ptr<A>
将始终调用delete p;
, where the static type of p
is A*
. ,其中
p
的静态类型是A*
。
Your code compiles because the default_delete<T>
copy constructor can accept another default_delete<U>
instance as long as U*
is implicitly convertible to T*
, which it is in this case. 您的代码编译是因为
default_delete<T>
复制构造函数可以接受另一个default_delete<U>
实例,只要U*
可以隐式转换为T*
,在这种情况下就是这样。 However, polymorphic deletion of the derived class object through base class pointer, when the base class destructor is not virtual
is undefined behavior. 但是,当基类析构函数不是
virtual
时,通过基类指针对派生类对象进行多态删除是未定义的行为。
The second problem of custom deleters for each type can be solved by supplying a custom deleter that is a lambda which first casts the argument to the appropriate type before passing it on to that object's deleter. 每种类型的自定义删除的第二个问题可以通过提供一个自定义删除器来解决,该删除器是一个lambda,它首先将参数转换为适当的类型,然后再将其传递给该对象的删除器。
For instance, 例如,
template<typename T>
void CustomDeleter(T *t)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
delete t;
}
std::vector<std::unique_ptr<A, void(*)(A *)>> myArray;
myArray.push_back(
std::unique_ptr<A, void(*)(A *)>(new A(), [](A *a){
CustomDeleter(a); }));
myArray.push_back(
std::unique_ptr<A, void(*)(A *)>(new B(), [](A *a){
CustomDeleter(static_cast<B*>(a)); }));
myArray.push_back(
std::unique_ptr<A, void(*)(A *)>(new C(), [](A *a){
CustomDeleter(static_cast<C*>(a)); }));
When the vector
goes out of scope, this prints: 当
vector
超出范围时,将打印:
void CustomDeleter(T*) [with T = A]
void CustomDeleter(T*) [with T = B]
void CustomDeleter(T*) [with T = C]
No, the type of the custom deleter is a template parameter to std::unique_ptr
. 不,自定义删除器的类型是
std::unique_ptr
的模板参数。 Your easiest solution would be to add a member variable to the custom deleter: 最简单的解决方案是将成员变量添加到自定义删除器:
struct custom_deleter
{
int m_kind;
custom_deleter(int kind)
{
m_kind = kind;
}
void operator()(A* p)
{
switch (m_kind)
{
case 0:
CustomFree0(p);
break;
case 1:
CustomFree1(p);
break;
//...
}
}
};
And then make CustomAlloc
build the appropriate custom_deleter
and pass it to the constructor of std::unique_ptr<A, custom_deleter>
as second parameter. 然后使
CustomAlloc
构建相应的custom_deleter
并将其作为第二个参数传递给std::unique_ptr<A, custom_deleter>
的构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.