如果未使用 shared_ptr 定义虚拟析构函数,是否有任何优势

Is there any advantage if virtual destructor is not defined with shared_ptr

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

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

完全不声明析构函数有什么好处?

考虑以下代码

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. 删除了动态调度,允许更有效的静态调度甚至更容易的内联。让编译器自行证明并减少动态到静态分派是 non-trivial.

  2. 从 vtable 中删除了 deallocating-dtor 和 just-dtor 的条目。因此,如果其中任何一个实际上未被使用,那么证明起来要容易得多,从而有助于消除无用代码。

在宏伟的计划中,这两种影响通常都是微不足道的:

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

  2. 如果有任何实例,将需要两者之一(deallocating-dtor 和 just-dtor),并且与前代表一样,同时拥有两者只是微不足道的额外指令到后者。几乎不值得考虑。

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