【发布时间】:2023-03-08 11:33:01
【问题描述】:
考虑这个例子:
#include <cstdio>
#include <memory>
struct base
{
base( int i ): i(i) { printf("base ctor\n"); }
~base() { printf("base non-virtual dtor\n"); } // non-virtual
int i;
};
struct derived : public base
{
char* s;
derived(int i): base(i), s(new char[i] )
{
printf("derived ctor\n");
}
~derived()
{
printf("derived dtor\n");
delete [] s;
}
};
int main()
{
printf("Success\n");
//raw pointer
printf("RAW-POINTER\n");
{
base* b = new derived(2);
// ......
delete b; //here memory leak, but it's old- and error-prone code.
}
printf("---END-RAW-POINTER--\n");
//unique-ptr
printf("UNIQUE_PTR\n");
{
// I would that, this doesn't compile, because base- has not virtual destructor.
std::unique_ptr<base> bu( new derived(3) ); // here still memory leak !!!!
}
printf("--END-UNIQUE_PTR--\n");
return 0;
}
代码std::unique_ptr<base> bu( new derived(3) ); 易于使用std::has_virtual_destructor 类型特征禁止。
Live code
那么为什么要编译上面的代码呢?这是标准允许的吗?
编辑:有趣,但 std::shared_ptr 有效,即基础和派生 dtor 都会调用:
printf("SHARED_PTR\n");
{
std::shared_ptr<base> b(new derived(3));
}
printf("--END-SHARED_PTR--\n");
Output:
SHARED_PTR
base ctor
derived ctor
derived dtor
base non-virtual dtor
--END-SHARED_PTR--
为什么 std::shared_ptr 可以调用派生类 dtor,而 std::unique_ptr 不能???
EDIT2:简单我需要类似的东西:
template< typename T, typename D = default_deleter<T> >
class unique_ptr{
.............
template< typename U >
unique_ptr( U* u ) if ( U != T && T - is class && T is base of U, and D - is default_deleter, and T - has not virtual destructor ) then = delete this ctor.
};
【问题讨论】:
-
@Brian Bi:并非所有都使用自定义删除器,在许多情况下用户使用 default_deleter 进行限制。
-
std::shared_ptr将工作。它将调用基类和派生类的析构函数:ideone.com/Nc542V -
如果你使用
public继承,你应该定义析构函数为virtual。 (stackoverflow.com/questions/270917/…) -
删除
p的静态类型与动态类型不同的指针p是未定义行为,但不是禁止的(= 不是格式错误的)。此外,您必须检查unique_ptr的 dtor,因为您可以提供不完整的类型,只要它们在unique_ptr的 dtor 实例化时是完整的(或他们的 dtor 是微不足道的)。
标签: c++ c++11 polymorphism unique-ptr