为什么派生类的析构函数是在对基类的const引用上调用的?

Xeo*_*Xeo 7 c++ inheritance reference

GMan的回答中,restore_base类的析构函数不是virtual,所以我一直想知道它是如何工作的.通常restorer_base,在对象超出范围之后,您只希望执行析构函数,但似乎restorer_holder真正调用了派生的析构函数.有人关心开导我吗?

zwo*_*wol 18

需要虚拟析构函数的标准情况是

void foo()
{
   scoped_ptr<Base> obj = factory_returns_a_Derived();

   // ... use 'obj' here ...
}
Run Code Online (Sandbox Code Playgroud)

而你不这样做的标准情况是

void foo()
{
   Derived obj;

   // ... use 'obj' here ...
}
Run Code Online (Sandbox Code Playgroud)

GMan的代码做了一些有点棘手的事情,结果证明等同于第二种情况:

void foo()
{
   Base& obj = Derived();

   // ... use 'obj' here ...
}
Run Code Online (Sandbox Code Playgroud)

obj是一个简单的参考; 通常,它根本不会触发析构函数.但它是从一个匿名临时对象初始化的,其静态类型 - 编译器已知 - 是Derived.当该对象的生命周期结束时,编译器将调用Derived析构函数.通常,匿名临时对象在创建它的表达式的末尾消亡,但是对于初始化引用的临时对象有一个特例:它们一直存在直到引用本身死亡,这就是范围的结束.因此,您获得了伪scoped_ptr行为,并且您不需要虚拟析构函数.

编辑:既然现在这已经拿出了两次:参考必须const为这个特殊的规则适用.C + 98 [class.temporary]/5:

第二个上下文[在完整表达式结束时不销毁临时对象]是指引用绑定到临时对象时.引用绑定的临时对象或作为临时绑定的子对象的完整对象的临时对象在引用的生命周期内持续存在...

强调我的.const在这种语言中没有提及,因此参考不必如此const.

编辑2:标准中的其他规则禁止创建非左值的临时对象的非常量引用.我怀疑至少有一些临时对象左值,但我不确定.无论如何,这不会影响这条规则.对于临时对象的非常量引用仍然是正式的,即使没有严格符合要求的C++程序可以创建这样的引用,它也会延长它们的生命周期.这可能看起来很荒谬,但你应该从字面上和迂腐中阅读这个标准.每个字都很重要,每个字都不重要.