如果未使用shared_ptr定义虚拟析构函数,有什么好处?

问题描述

当我们将shared_ptr与多态类一起使用时,由于类型为Deleted 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中删除了deallocating-dtor和just-dtor条目。因此,如果实际上未使用任何一个,则更容易证明,从而有助于消除无效代码。

在事物的宏伟计划中,两种效果通常都是很小的:

  1. 一次动态调度(最糟糕的情况)与取消分配的成本相比显得相形见。

  2. 如果有任何实例,则需要两个(deallocating-dtor和just-dtor)中的一个,并且由于前者委托后者,所以两者都有少量琐碎的附加指令。几乎不值得考虑。

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...