草庐IT

c++ - 智能指针 + "this"被认为是有害的?

coder 2023-06-04 原文

在使用智能指针的 C++ 项目中,例如 boost::shared_ptr ,关于使用“this”的好的设计理念是什么?

考虑一下:

  • 存储包含在任何智能指针中的原始指针供以后使用是很危险的。您已经放弃了对对象删除的控制,并相信智能指针会在正确的时间执行此操作。
  • 非静态类成员本质上使用 this 指针。这是一个原始指针,无法更改。

  • 如果我曾经存储 this在另一个变量中或将其传递给另一个函数,该函数可能将其存储以备后用或将其绑定(bind)在回调中,我正在创建错误,当有人决定创建指向我的类的共享指针时,这些错误会被引入。

    鉴于此,我什么时候明确使用 this 合适指针? 是否有设计范式可以防止与此相关的错误?

    最佳答案

    错误的问题

    In a C++ project that uses smart pointers



    这个问题实际上与智能指针无关。这只是关于所有权。

    智能指针只是工具

    他们没有改变所有权的概念,尤其是。 需要在您的程序中拥有明确定义的所有权 ,所有权可以自愿转让,但不能由客户取得的事实。

    您必须了解智能指针(还有锁和其他 RAII 对象)表示一个值,并且同时表示一个与该值对应的关系。 A shared_ptr是对对象的引用并建立关系:对象在此之前不得销毁shared_ptr , 当这个 shared_ptr被销毁,如果它是最后一个别名该对象,则必须立即销毁该对象。 ( unique_ptr 可以被视为 shared_ptr 的一个特例,其中根据定义零别名,所以 unique_ptr 总是最后一个别名对象。)

    为什么应该使用智能指针

    建议使用智能指针,因为它们只用变量和函数声明来表达很多。

    智能指针只能表达明确定义的设计,它们并不能消除定义所有权的需要。相比之下,垃圾回收不需要定义谁负责内存释放。 (但不要取消定义谁负责其他资源清理的需要。)

    即使在非纯函数式垃圾收集语言中,您也需要明确所有权:如果其他组件仍然需要旧值,您不想覆盖对象的值。在 Java 中尤其如此,其中可变数据结构的所有权概念在线程程序中极为重要。

    原始指针呢?

    使用原始指针并不意味着没有所有权。它只是没有通过变量声明来描述。它可以在注释、设计文档等中进行描述。

    这就是为什么许多 C++ 程序员认为使用原始指针而不是足够的智能指针是 劣质 :因为它的表现力较差(我故意避免使用“好”和“坏”这两个词)。我相信 Linux 内核会更易读一些 C++ 对象来表达关系。

    您可以使用或不使用智能指针来实现特定设计。适当使用智能指针的实现将被许多 C++ 程序员认为是优越的。

    你真正的问题

    In a C++ project, what is a good design philosophy regarding use of "this"?



    这太含糊了。

    It's dangerous to store the raw pointer for later use.



    为什么你需要一个指针供以后使用?

    You've given up control of object deletion and trust the responsible component to do it at the right time.



    实际上,某些组件负责变量的生命周期。你不能承担责任:它必须转移。

    If I ever store this in another variable or pass it to another function which could potentially store it for later or bind it in a callback, I'm creating bugs that are introduced when anyone decides to use my class.



    显然,由于没有通知调用者该函数将隐藏一个指针并稍后在不受调用者控制的情况下使用它,因此您正在创建错误。

    解决方案显然是:
  • 将处理对象生命周期的责任转移给函数
  • 确保指针仅在调用者的控制下保存和使用

  • 只有在第一种情况下,您可能最终会在类实现中使用智能指针。

    你的问题的根源

    我认为您的问题是您正在努力使用智能指针使问题复杂化。智能指针是使事情变得更容易,而不是更难的工具。如果智能指针使您的规范复杂化,那么就更简单的事情重新考虑您的规范。

    在出现问题之前,不要尝试引入智能指针作为解决方案。

    仅引入智能指针来解决特定的明确定义的问题。因为你没有描述一个具体的明确定义的问题,无法讨论具体的解决方案 (是否涉及智能指针)。

    关于c++ - 智能指针 + "this"被认为是有害的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/382166/

    有关c++ - 智能指针 + "this"被认为是有害的?的更多相关文章

    1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

      我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

    2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

      我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

    3. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

      我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

    4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

      为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

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

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

    6. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

      我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

    7. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

      我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

    8. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

      我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

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

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

    10. ruby - RVM "ERROR: Unable to checkout branch ."单用户 - 2

      我在新的Debian6VirtualBoxVM上安装RVM时遇到问题。我已经安装了所有需要的包并使用下载了安装脚本(curl-shttps://rvm.beginrescueend.com/install/rvm)>rvm,但以单个用户身份运行时bashrvm我收到以下错误消息:ERROR:Unabletocheckoutbranch.安装在这里停止,并且(据我所知)没有安装RVM的任何文件。如果我以root身份运行脚本(对于多用户安装),我会收到另一条消息:Successfullycheckedoutbranch''安装程序继续并指示成功,但未添加.rvm目录,甚至在修改我的.bas

    随机推荐