Khu*_*hid 15 c++ polymorphism unique-ptr c++11
考虑这个例子:
#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;
}
Run Code Online (Sandbox Code Playgroud)
代码std::unique_ptr<base> bu( new derived(3) );很容易禁止使用std :: has_virtual_destructor类型特征.
实时代码
那么为什么编译上面的代码呢?这是标准允许的吗?
编辑:有趣,但是std :: shared_ptr工作,即base和derived 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--
Run Code Online (Sandbox Code Playgroud)
为什么std :: shared_ptr可以调用dervied类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.
};
Run Code Online (Sandbox Code Playgroud)
moc*_*ace 14
之间的差unique_ptr和shared_ptr在标准的语言,相对于它们的析构函数(和构造函数).适用于您的示例的两个智能指针的删除者的语言类似但略有不同:
[20.7.1.2.2] unique_ptr destructor ... If get() == nullptr there are no efects. Otherwise get_deleter()(get()). [20.7.2.2.2] shared_ptr destructor ... if *this owns an object p and a deleter d, d(p) is called.
您可以看到,在两种情况下,标准都表示要调用删除器,但不同之处在于如何确定删除器,并unique_ptr删除通过它获取的指针get(),同时shared_ptr删除对象.这种区别很重要.看看这两个类的构造函数是如何不同的:
的shared_ptr定义如下:
template <class T>
class shared_ptr {
...
template<class Y> explicit shared_ptr(Y* p);
Run Code Online (Sandbox Code Playgroud)
虽然unique_ptr明确的单参数的构造函数是,
template <class T, class D = default_delete<T>>
class unique_ptr {
...
explicit unique_ptr(pointer p) noexcept;
...
Run Code Online (Sandbox Code Playgroud)
观察到unique_ptr只获取类型的默认删除,delete在您的情况下将是plain ,并存储指针.但是,shared_ptr<T>构造函数不在T(!)上进行模板化Y,它是根据构造它的对象的类型进行模板化的.因此,在您的方案中,
std::shared_ptr<base> b(new derived(3));
Run Code Online (Sandbox Code Playgroud)
在shared_ptr将与构造T=base,但是Y=derived,允许明确地销毁派生的对象,并在你的例子没有内存泄漏.
虽然您无法更改标准,但您可以做的是从unique_ptr项目中继承,或者提供自己的包装来强制执行所需的行为.例如,
namespace {
template <class T>
struct checked_delete : public std::default_delete<T> {
static_assert(std::has_virtual_destructor<T>::value, "");
};
template <class T, class D = checked_delete<T>, class U>
std::unique_ptr<T, D>
make_unique_ptr(U* p) { return std::unique_ptr<T, D>(p, D()); }
}
// now this won't compile, because checked_delete<base> will not compile:
auto bu = make_unique_ptr<base>(new derived(3));
Run Code Online (Sandbox Code Playgroud)
并非所有 unique_pointers 都以多态方式使用:
std::unique_ptr<int> p(new int(42));
Run Code Online (Sandbox Code Playgroud)
这不会符合您提出的限制。与类相同:
std::unique_ptr<YourClassHere> p(new YourClassHere);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3321 次 |
| 最近记录: |