首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >容器拥有的对象的确定性销毁(或者如何将唯一的(std.typecons.Unique)放入D Phobos容器)?

容器拥有的对象的确定性销毁(或者如何将唯一的(std.typecons.Unique)放入D Phobos容器)?
EN

Stack Overflow用户
提问于 2014-07-21 04:49:59
回答 1查看 57关注 0票数 2

我正在尝试实例化一个充满独特资源的容器,以确保当容器被销毁时,容器所管理(拥有)的所有项也会被销毁,并自动正确。

以下(非唯一)代码的行为与预期相同。注意,Foo对象在应用程序退出之前不会被销毁( GC最终会收回它们)。暂时忽略GC,在销毁DList时不确定地销毁它们--在“退出作用域”消息中--容器中的对象在应用程序生命周期内实际上已经泄漏:

代码语言:javascript
复制
import  std.stdio,
        std.container,
        std.range,
        std.typecons,
        std.random;

class Foo
{
  this()
  {
    debug( List ) writefln( "  %s constructor invoked", this.classinfo.name );
  }

  ~this()
  {
    debug( List ) writefln( "  %s destructor invoked", this.classinfo.name );
  }
}


int main( string[] args ) {
  debug( List ) writeln( "main():" );
  {
    debug( List ) writeln( "  entering scope" );
    scope auto list = DList!( Foo )();

    immutable ELEMENTS_TO_MAKE = 5;
    for( auto i = 0; i < ELEMENTS_TO_MAKE; ++i )
    {
      Foo foo = new Foo();
      list.insertBack( foo ); 
    }
    debug( List ) writefln( "  Length: %s elements in container", walkLength( list[] ) ); 
    debug( List ) writeln( "  exiting scope" );
  }
  debug( List ) writeln( "  exiting app" );
  return 0;
}

提供如下输出,如预期的那样:

代码语言:javascript
复制
main():
  entering scope
  main.Foo constructor invoked
  main.Foo constructor invoked
  main.Foo constructor invoked
  main.Foo constructor invoked
  main.Foo constructor invoked
  Length: 5 elements in container
  exiting scope
  exiting app
  main.Foo destructor invoked
  main.Foo destructor invoked
  main.Foo destructor invoked
  main.Foo destructor invoked
  main.Foo destructor invoked

但是当我更新这个应用程序时,它就会崩溃:

代码语言:javascript
复制
...

int main( string[] args ) {
  debug( List ) writeln( "main():" );
  {
    debug( List ) writeln( "  entering scope" );
    scope auto list = DList!( Unique!Foo )();

    immutable ELEMENTS_TO_MAKE = 5;
    for( auto i = 0; i < ELEMENTS_TO_MAKE; ++i )
    {
      Unique!Foo foo = new Foo();
      list.insertBack( foo.release );  //looks like Phobos containers can't hold Unique's??? :( 
    }
    debug( List ) writefln( "  Length: %s elements in container", walkLength( list[] ) ); 
    debug( List ) writeln( "  exiting scope" );
  }
  debug( List ) writeln( "  exiting app" );
  return 0;
}

上面的代码提供了以下输出:

代码语言:javascript
复制
main():
  entering scope
  main.Foo constructor invoked
  main.Foo destructor invoked
Bus error: 10

注释掉list.insertBack()行会使总线错误10停止。对于如何自动和确定性地销毁容器拥有的对象,有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-21 14:13:20

这里最主要的问题是,Phobos DList没有获得对象的所有权--它在内部使用GC管理的Node*,所以即使您修复了导致所看到的总线错误的空指针问题,您仍然无法得到您想要的销毁模式。

进入细节:Unique是错误的,它不应该是可复制的,但它是.它声称是多态的,但它只是极小的多态,并且它在尝试删除其有效负载之前不检查null,这会导致您看到的总线错误。

坦白说,我觉得自上而下都不对。我的建议是:不要用它。

现在,如果您使用@disable this(this)编写了一个更正确的唯一值,那么在析构函数中进行空检查,等等.您会发现它不适用于std.container.DList,因为Dlist在内部分配东西;它不使用移动操作。带有Dlist的正确的Dlist不能编译。

那么,让我们试试RefCounted。Phobos的RefCounted不适用于类。太棒了。嗯,我们可以很容易地写我们自己的,我只是做了一个快速和草率的一个在这里refcounted.d U是一个更正确的独特和RC是一个更正确的RefCounted。

现在我们可以看到倒计时的变化..。但从来没有打到零。为什么?打开DList的源代码,您将看到它在内部使用new Node

因此,这些都是GC拥有的,因此在收集器运行之前不会销毁。

总之,您必须编写自己的DList容器。看起来std.container.Array实际上/ so /取得所有权,它的析构函数确实破坏了有效负载(尽管它没有释放有效负载内存-所以它将调用析构函数。

因此,如果您使用更正确的ref计数实现,您可以使用Array --我在上面发布的链接就是这样做的,这样您就可以看到它是有效的,与DList的变化最小--但是如果您确实想要一个链接列表,就必须自己动手并在那里编写一个正确的析构函数。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24857925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档