Hon*_*hen 10 c++ smart-pointers unique-ptr virtual-destructor c++11
我们知道如果有虚函数那么基类析构函数也应该被标记为虚拟,否则当显式地如果我们希望删除带有基类指针的派生对象,则基础析构函数应该被标记为虚拟,否则是未定义的行为.deleted使用基类指针时它是未定义的行为
例如,
struct Base {
virtual void greet() { std::cout << "base\n"; }
};
struct Derived : public Base {
virtual void greet() override { std::cout << "derived\n"; }
};
Run Code Online (Sandbox Code Playgroud)
呼叫
Base *b = new Derived;
b->greet();
delete (b);
Run Code Online (Sandbox Code Playgroud)
-wdelete-non-virtual-dtor时,clang(类似gcc)会发出这样的警告:
delete called on 'Base' that has virtual functions but non-virtual destructor
Run Code Online (Sandbox Code Playgroud)
但他们都没有报告智能指针的警告:
std::unique_ptr<Base> sb = std::make_unique<Derived>();
// std::unique_ptr<Base> sb = std::unique_ptr<Derived>(new Derived);
sb->greet();
Run Code Online (Sandbox Code Playgroud)
我想这仍然导致未定义的行为,对吧?
T.C*_*.C. 13
是的,它仍然是未定义的行为.问题是delete调用发生在内部std::default_delete,这是在系统头内.默认情况下,编译器不会为系统标头中的代码生成警告.
如果你通过-Wsystem-headers,你会看到警告.不幸的是,它被埋在一堆其他警告中.
其他答案尚未提及:
这个问题只存在于unique_ptr,而不是为了shared_ptr.
这两个智能指针都可以有自定义删除器; 但unique_ptr默认为删除基指针,shared_ptr默认为删除派生指针(如果使用make_shared<Derived>或等效).
解决此问题的另一种方法是提供自己的自定义删除器unique_ptr,删除派生指针.对于您希望避免引入vtable的开销的情况,这可能是一个很好的解决方案.
进一步阅读:unique_ptr删除, shared_ptr删除
| 归档时间: |
|
| 查看次数: |
1806 次 |
| 最近记录: |