如果虚拟析构函数不是用shared_ptr定义的,有什么好处吗



当我们将shared_ptr与多态类一起使用时,由于类型已擦除的deleter,我们不需要虚拟析构函数。

但是在简单的情况下定义析构函数有意义吗。

根本不声明析构函数有什么好处?

考虑以下代码

struct Base {                                                                   
/*virtual*/ ~Base() { std::cout << "Base Dtor" << std::endl; }  
OR
/*virtual*/ ~Base() = default;              
virtual void foo() = 0;                                                       
};                                                                              
          
struct Derived : Base {                                                         
~Derived() { std::cout << "Derived Dtor" << std::endl; }                      
void foo() override { std::cout << "foo" << std::endl; }                      
};                                                                              
          
int main() {                                                                    
std::shared_ptr<Base> ptr = std::make_shared<Derived>();                      
}

是的,当然,即使对于多态类型,也没有虚拟dtor有好处:

  1. 删除了动态调度,允许更高效的静态调度,甚至更容易的内联。让编译器证明这一点并将动态调度减少到静态调度本身是非常重要的。

  2. 从vtable中删除了用于取消分配dtor的条目,仅删除了dtor。因此,如果其中一个实际上是未使用的,那么就更容易证明,有助于消除死代码。

在总体方案中,这两种影响通常都很小:

  1. 一个动态调度(在最坏的情况下(与解除分配的成本相比相形见绌。

  2. 如果存在任何实例,则需要两种方法中的一种(释放dtor和仅分配dtor(,而同时拥有这两种方法只需要少量的额外指令,因为前者委托后者。这几乎不值得思考。

另一方面,如果您(或其他人(出现错误(或忽略策略(并编写依赖于此的代码,那么没有虚拟dtor的基础可能非常危险。未定义的行为很少是有趣的
这就是为什么每个人都坚持认为,如果发生任何动态多态性(任何虚拟函数、dtor、base或具有相同功能的base(,那么dtor最好也是虚拟的!

最新更新