但是可以通过引用实现相同的功能吗?

MCanvasFont.h

namespace Impl {
    class FontDelegate;
}

class MCanvasFont
{
public:
    MCanvasFont();
    virtual ~MCanvasFont();

protected:
    // Reference count
    long m_cRef;

    // agg font delegate
    const Impl::FontDelegate& m_font;
}

MCanvasFont.cpp
// helpers
#include "ImplHelpers/FontDelegate.h"

MCanvasFont::MCanvasFont()
: m_cRef(1),
  m_font(Impl::FontDelegate() )
{
    // constructor's body
}

附言这段代码在G++编译时没有任何问题。

最佳答案

您的程序中存在错误,并且在构造函数的初始化程序列表中:

MCanvasFont::MCanvasFont()
: m_cRef(1),
  m_font(Impl::FontDelegate() ) // <--- BANG
{
Impl::FontDelegate()的问题在于它构造了一个临时对象。这不会超过构造函数的寿命-实际上,它实际上是在进入构造函数主体之前被销毁的,因为它的生命周期就是它所出现的表达式的生命周期。因此,您的m_font引用立即无效。

尽管您可以使用手动分配的对象(*new Impl::FontDelegate())对其进行初始化,但是如果分配失败,则您将处于未定义的区域,除非您在运行时启用了异常。无论如何,您仍然还必须在析构函数中对对象进行delete。因此,引用实际上并不会给您带来任何好处,它只是使一些不自然的代码成为可能。我建议改用const指针:
const Impl::FontDelegate* const m_font;

编辑:只是为了说明问题,请使用以下等效示例:
#include <iostream>

struct B
{
    B() { std::cout << "B constructed\n"; }
    ~B() { std::cout << "B destroyed\n"; }
};

struct A
{
    const B& b;
    A() :
        b(B())
    {
        std::cout << "A constructed\n";
    }
    void Foo()
    {
        std::cout << "A::Foo()\n";
    }
    ~A()
    {
        std::cout << "A destroyed\n";
    }
};

int main()
{
    A a;
    a.Foo();
}

如果运行此命令,输出将是:
B constructed
B destroyed
A constructed
A::Foo()
A destroyed

因此b几乎立即无效。

09-10 03:28
查看更多