双重检查:从成员函数传递内部引用

时间:2014-02-07 17:50:41

标签: python c++ boost-python

如果我有

//test.hpp
class iA
{
public:
  virtual ~iA(){}
  virtual void foo() const = 0;
};


class A1 : public iA
{
public:
  virtual ~A1(){}
  A1(){}
  virtual void foo() const;
};

class A2 : public iA
{
public:
  virtual ~A2(){}
  A2(){}
  virtual void foo() const;
};

class B
{
public:
  B(int a);
  B(const std::string& s);

  ~B() {if (a_) {delete a_; a_ = 0;}}

  const iA& a() const
  {
    return *a_;
  }

  void foo() const;


private:
  iA* a_;
};

我在下面编写了python包装器:

struct iAWrap : iA, boost::python::wrapper<iA>
{
  void foo() const
  {
    this->get_override("foo");
  }
};

BOOST_PYTHON_MODULE(libtest)
{
    using namespace boost::python;
    def("greet", greet);

    class_<iAWrap, boost::noncopyable>("iA")
      .def("foo",pure_virtual(&iA::foo))
        ;

    class_<B>("B",init<int>())
        .def(init<std::string>())
        .def("foo", &B::foo)
        .def("a", &B::a, return_internal_reference<1>())//line I have a question about
        ;
}

return_internal_reference&lt; 1&gt;将返回的A引用的生命周期绑定到B的不可见“self”参数

1 个答案:

答案 0 :(得分:1)

它一直帮助我把它想象成被返回的对象(A扩展它的拥有对象(B)的生命周期至少只要返回的对象(A)。

return_internal_reference文档描述了owner_arg

  

包含要返回引用或指针的对象的参数的索引。如果用于包装成员函数,则参数1是目标对象(*this)。

在原始代码中,owner_arg显式设置为1,表示成员函数中的this对象(B)(&B::a) invocation是包含返回对象(iA)的对象。

with_custodian_and_ward_postcall记录了终身行为效应,其中指出:

  

ward 对象在保管人 [...]

之后才会销毁

return_internal_reference文档的类概要简化了实际的继承链:

template <std::size_t owner_arg = 1, class BasePolicy_ = default_call_policies>
struct return_internal_reference
    : with_custodian_and_ward_postcall<0, owner_arg, BasePolicy_>
{
  // ...
};

return_internal_reference结构:

  • 明确提供0作为custodian,将iA的返回对象(postcall())设置为关系中的保管人。 / LI>
  • owner_argreturn_internal_reference默认值设置为1)作为ward,将*this对象(B)设置为<在关系中他们 。

因此,在B 保管人对象之后,iA ward 对象才会被销毁。


以下是演示此行为的完整简单示例:

#include <iostream>
#include <boost/python.hpp>

class Foo
{
public:
  Foo()  { std::cout << "Foo()" << std::endl; }
  ~Foo() { std::cout << "~Foo()" << std::endl; }
};

class Bar
{
public:
  Bar()  { std::cout << "Bar()" << std::endl; }
  ~Bar() { std::cout << "~Bar()" << std::endl; }
  Foo& foo() { return foo_; }
private:
  Foo foo_;
};

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::class_<Foo>("Foo");
  python::class_<Bar>("Bar")
    .def("foo", &Bar::foo, python::return_internal_reference<>())
    ;
}

Interactive Python:

>>> import example
>>> bar = example.Bar()
Foo()
Bar()
>>> foo = bar.foo()
>>> del bar
>>> del foo
~Bar()
~Foo()

请注意,bar ward 对象的生命周期至少与foo 保管人对象一样长。