草庐IT

c++ - 正确的(资源处理)零规则在哪里?

coder 2023-11-12 原文

就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the help center为指导。




8 年前关闭。




这里有一篇文章讨论了一个名为 Rule of Zero 的习语。 .
这是摘录:

class module {
public:
    explicit module(std::wstring const& name)
    : handle { ::LoadLibrary(name.c_str()), &::FreeLibrary } {}

    // other module related functions go here

private:
    using module_handle = std::unique_ptr<void, decltype(&::FreeLibrary)>;

    module_handle handle;
};
它重复使用 unique_ptr RAII 功能,因此您无需关心实现令人生畏且冗长的五规则包装器。
以这种方式呈现(使用 unique_ptr 管理基于句柄的资源,那样),对我来说它看起来像是一个黑客,而不是它试图解决的问题的最佳解决方案。隐含地假设了太多假设:
  • 一种是能够对等并使用基本类型#define (或 typedef)HANDLE建立在。对我来说,这应该是隐藏的知识,解决方案完全基于界面提供的内容:HANDLE .
  • 句柄,可以是任何东西,它们不需要是指针类型。

  • 我想使用这个习语,但在我偶然发现的许多情况下它都不够用。
    这个以句柄为中心的 RAII 包装器是否已经完成并可以在一些很酷的库中使用?是不是每个人都在使用这样的工具而我不知道? (我认为这样的工具不仅适用于一种,而且适用于许多类型的所有权)
    编辑 1
    这与平台特定的资源句柄无关,例如,glGenLists返回一种句柄,它是一个 GLuint , 你应该调用 glDeleteLists在上面。如前所述,资源句柄不需要是指针类型,并且不应假设这种假设。
    编辑 2
    零规则,在前一个示例中,通过使用现有工具 unique_ptr , 显示为句柄管理的一个很好的快捷方式。它需要的额外假设使它达不到要求。正确的假设是您有一个句柄,并且您有一个资源销毁函数来销毁句柄给出的资源。 handle 是否为void * , GLuint ,无论如何,这应该无关紧要,更糟糕的是,甚至不应该要求对等 HANDLE内型。出于管理 RAII 方式的目的,如果习语告诉它对此有好处,并且不能应用于这种情况,我觉得这对它不利,最后使用给定的工具。
    编辑 3
    一个说明性的情况是,假设您负责使用新的 3rd 方 C 库。它包含一个 FooHandle create_foo()和一个 void destroy_foo(FooHandle) .所以你想,“让我们通过使用零规则来使用 FooHandle”。好的,您可以使用 unique_ptr , unique_ptr你问自己什么?是 FooHandle指针?,所以你使用 unique_ptrFooHandle未曝光 基本类型?是int ?,以便您可以直接使用它,或者最好(重新)typedef像@NicolBolas 在他的回答中所做的事情。对我来说,似乎很清楚,即使在如此微不足道的情况下,unique_ptr已经显示出不适合管理资源句柄。
    免责声明:
    我试图重新表述并更好地表达自己:
  • Is there a proper 'ownership-in-a-package' for 'handles' available?

  • 编辑 4
    我找到了我要找的东西,我把它作为重新提出的问题的答案:https://stackoverflow.com/a/14902921 .

    最佳答案

    背景:零规则

    首先也是最重要的,那篇文章是关于一个更一般的想法,而不仅仅是它提到的资源句柄包装器示例。

    关键是当一个类包含具有“非平凡”所有权语义的成员时,该类应该 不是 负责机械师 确保包含类的正确值语义(复制、分配、移动、销毁)。相反,每个组成部分都应该自己适本地实现“Rule-Of-3+”,以便复合类可以利用编译器默认的特殊成员。

    此外,新的标准智能指针类型大大简化了为所包含的类型实现这一点的任务。在大多数情况下,需要注意的成员是指针:std::unique_ptr、shared_ptr、weak_ptr 解决了这里的需求。

    对于自定义资源类型,您可能需要编写 Rule-Of-3+ 包装器类,但只需 一次 .您的其他类(class)将受益于零规则。



    子弹:

    • One is able to peer and use the base type the #define (or typedef) HANDLE is built upon. For me this should be hidden knowledge, and a solution be based exclusively on what the interface makes available, HANDLE.


    答:90% 的时间您可以(并且应该)使用 std::unique_ptr<>带有自定义删除器。清理的知识和责任仍然由分配器负责。它应该的方式。

    在其余情况下,您必须为您的特定资源编写一个单独的包装类,否则该类不受支持。

    • Handles, can be anything, they're not required to be pointer types.


    他们能。你会看例如提升::可选。或者写那个包装器。关键是,你想要它隔离 为资源。您不想使碰巧拥有/包含此类资源的类复杂化。

    关于c++ - 正确的(资源处理)零规则在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14865919/

    有关c++ - 正确的(资源处理)零规则在哪里?的更多相关文章

    1. ruby - 如何指定 Rack 处理程序 - 2

      Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

    2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

      我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

    3. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

      我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

    4. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

      当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

    5. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

      question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

    6. ruby - 我可以将我的 README.textile 以正确的格式放入我的 RDoc 中吗? - 2

      我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:

    7. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

      我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

    8. ruby - 调用其他方法的 TDD 方法的正确方法 - 2

      我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent

    9. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

      我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

    10. ruby - 使用 `+=` 和 `send` 方法 - 2

      如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

    随机推荐