为什么QuantLib会引入Handle类?

cam*_*ino 7 quantlib

我检查这张幻灯片,但仍然没有得到:

1) what problem does Handle sovled?

2) what is the benefit to add the Handle class?
Run Code Online (Sandbox Code Playgroud)

从它的源代码,我无法得到任何线索:

   template <class Type>
    class Handle {
      protected:
        class Link : public Observable, public Observer {
          public:
            explicit Link(const shared_ptr<Type>& h =
                                         shared_ptr<Type>());
            void linkTo(const shared_ptr<Type>&);
            bool empty() const;
            void update() { notifyObservers(); }
          private:
            shared_ptr<Type> h_;
        };
        boost::shared_ptr<Link<Type> > link_;
      public:
        explicit Handle(const shared_ptr<Type>& h =
                                         shared_ptr<Type>());
        const shared_ptr<Type>& operator->() const;
        const shared_ptr<Type>& operator*() const;
        bool empty() const;
        operator boost::shared_ptr<Observable>() const;
    };

    template <class Type>
    class RelinkableHandle : public Handle<Type> {
      public:
        explicit RelinkableHandle(const shared_ptr<Type>& h =
                                         shared_ptr<Type>());
        void linkTo(const boost::shared_ptr<Type>&);
    };
Run Code Online (Sandbox Code Playgroud)

有人能给出一个更好的例子吗?

谢谢.

Lui*_*bio 7

简短的回答:Handle类是指向指针的智能指针.

到底有什么好处呢?例如,利用诸如的利率指数的实例Euribor6M.现在,它的构造函数处理一个收益期限结构,从中预测其未来的定价.如果我们用一个shared_ptr代替什么会改变?

我们来看一个用例.警告:我正在简化以避免编写太多代码,但这是我们拥有的合法用例.假设我们用一条平曲线初始化索引,首先:

shared_ptr<SimpleQuote> r = make_shared<SimpleQuote>(0.01);
shared_ptr<YieldTermStructure> curve =
    make_shared<FlatForward>(today, r, Actual360());

shared_ptr<InterestRateIndex> index = make_shared<Euribor6M>(curve);
Run Code Online (Sandbox Code Playgroud)

(在实际使用案例中,curve将是一组Euribor曲线,在一组报价率上引导).构造函数index获取传递shared_ptr<YieldTermStructure>的副本并将其副本存储为数据成员.在它建成之后,我们将把指数传递给其他工具(掉期,浮动利率债券等等).

如果利率发生变化,并且我们仍然持有r报价,我们的客户代码可以写入

r->setValue(0.015);
Run Code Online (Sandbox Code Playgroud)

由于rcurve是共享指针,这也将改变索引内部曲线副本的速率(因为两者curve及其内部复制index指向同一对象).因此,索引定价和依赖工具值也将发生变化.

但是,假设我们想要开始使用另一条曲线.在这种情况下,我们可能希望切换到插值曲线而不是平曲线:

vector<Date> dates = ... ;
vector<Rate> rates = ... ;
shared_ptr<YieldTermStructure> curve2 =
    make_shared<ZeroCurve>(dates, rates, Actual360());
Run Code Online (Sandbox Code Playgroud)

(在实际情况中,我们可能希望在不同的引号集上引导曲线或使用其他方式来建模速率).

我们怎么能告诉index它应该开始使用curve2?使用shared_ptr,我们不能.即使我们说:

curve = curve2;
Run Code Online (Sandbox Code Playgroud)

这将导致curve指向插补曲线,但是副本curveindex将继续指向旧的.这不是问题shared_ptr,但一般都有指针.你是如何解决的?通过添加另一层间接.如果你使用原始指针,你将开始使用指针指针.在我们的代码中,Handle做同样的事情:它"指向"a shared_ptr,并且实现为使得同一句柄的两个副本指向同一个shared_ptr.这样,如果你写:

shared_ptr<SimpleQuote> r = make_shared<SimpleQuote>(0.01);
shared_ptr<YieldTermStructure> curve =
    make_shared<FlatForward>(today, r, Actual360());
RelinkableHandle<YieldTermStructure> h(curve);

shared_ptr<InterestRateIndex> index = make_shared<Euribor6M>(h);
Run Code Online (Sandbox Code Playgroud)

你以后可以写:

h.linkTo(curve2);
Run Code Online (Sandbox Code Playgroud)

您持有的句柄及其内部副本index都将指向新曲线.

至于RelinkableHandle和之间的区别Handle:你只能打电话linkTo给前者.这个想法是你实例化一个RelinkableHandle,只传递副本Handle,所以你确保除了你之外没有人可以改变它指向的东西(使用const不起作用,因为constness可以被一个简单的副本抛弃).