2

Consider following code (minimal version):

#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();
}

This actually produces 'base' when using latest MinGW g++! Is that a compiler bug or am I missing something? Could someone test this in VS please?

I consider myself an experienced C++ programmer, constantly using polymorphism, stack-based references, temporary objects (C++ standard 12.2) etc. Therefore I know that lifetime lengthening should be applied.

This behaviour only occurs when defining a destructor in Base (virtual or not) and using a temporary, i. e. following usage produces 'derived':

int main()
{
    Derived d;
    Composite c(d);
    c.testRef();
}
4

2 回答 2

5
Composite c((Derived()));

这一行创建了一个 类型的临时对象Derived,将其传递给 的构造函数c,然后销毁该临时对象。在那之后,所有的赌注都被取消了。

于 2013-05-02T00:42:03.400 回答
2
Composite c((Derived()));

当您定义 Base 的析构函数和程序时,将执行 Composite 构造函数, Derived 和 Base 的析构函数。为了避免在 Base 的析构函数中调用 Base 的虚函数时出错(现在 Derived 已被析构),程序将虚函数点(也就是本测试代码的对象的地址)从派生的指向虚函数表移动到基地。如果你没有定义析构函数,那么什么都不做。该地址仍然指向 Derived 虚函数表。

 c.testRef();

ref 仍然获取对象的地址和虚函数表的地址,并调用表中的函数。所以差异是存在的。

我在 VC 8.0 中测试并检查内存。发生这种情况是因为某种“幸运”。

于 2013-05-02T03:41:45.273 回答