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

2024-05-20 14:38:48 发布

您现在位置: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\u internal\u reference<;1>;将A引用的生存期绑定到B的不可见“self”参数?你知道吗


Tags: a2stringreturnfoodefa1virtualpublic
1条回答
网友
1楼 · 发布于 2024-05-20 14:38:48

它总是帮助我将其视为返回的对象(A将其拥有的对象(B)的生存期延长到至少与返回的对象(A)一样长。你知道吗

^{}文档描述了owner_arg

The index of the parameter which contains the object to which the reference or pointer is being returned. If used to wrap a member function, parameter 1 is the target object (*this).

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

寿命行为效应记录在^{}中,其中说明:

The ward object will not be destroyed until after the custodian [...]

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,将postcall()的返回对象(iA)设置为关系中的保管者。你知道吗
  • 传递owner_argreturn_internal_reference默认为1)作为ward,将*this对象(B)设置为关系中的ward。你知道吗

因此,Bward对象在iA保管对象之后才会被销毁。你知道吗


下面是一个完整的简单示例,演示了这种行为:

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

交互式Python:

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

注意,barward对象的生存期被延长到至少与foo托管对象一样长。你知道吗

相关问题 更多 >