考虑以下代码(最小版本):
#include <iostream>
struct Base
{
virtual ~Base() {}
virtual void test() const { std::cout << "base"; }
};
struct Derived : public Base
{
void test() const { std::cout << "derived"; }
};
struct Composite
{
const Derived &ref;
Composite(const Derived &ref) : ref(ref) {}
void testRef() const { ref.test(); }
};
int main()
{
Composite c((Derived()));
c.testRef();
}
当使用最新的MinGW g ++时,这实际上会产生'基础'!这是编译器错误还是我错过了什么?有人可以在VS中测试一下吗?
我认为自己是一位经验丰富的C ++程序员,经常使用多态,基于堆栈的引用,临时对象(C ++标准12.2)等。因此我知道应该应用终身延长。
只有在Base(虚拟或非虚拟)中定义析构函数并使用临时,i时才会出现此行为。即以下用法产生'衍生':
int main()
{
Derived d;
Composite c(d);
c.testRef();
}
答案 0 :(得分:5)
Composite c((Derived()));
此行创建一个Derived
类型的临时对象,将其传递给c
的构造函数,然后销毁临时对象。之后,所有赌注都已关闭。
答案 1 :(得分:2)
Composite c((Derived()));
当您定义Base的析构函数并且程序离开Composite构造函数时,Derived和Base的析构函数被执行。为了避免在Base的析构函数中调用Base的虚函数时出错(现在Derived被破坏),程序将虚拟函数点(这只是该测试代码的对象的地址)从派生的指向虚函数表移动到基地。如果没有定义析构函数,则不执行任何操作。该地址仍指向Derived虚函数表。
c.testRef();
ref仍然获取对象的地址和虚函数表的地址,并调用表中的函数。所以存在差异。
我在VC 8.0中测试并检查内存。这是因为某种“幸运”。