草庐IT

c++ - 智能指针( boost )解释

coder 2023-04-24 原文

下面这组指针有什么区别?你什么时候在生产代码中使用每个指针,如果有的话?

示例将不胜感激!

  • scoped_ptr
  • shared_ptr
  • weak_ptr
  • intrusive_ptr

  • 你在生产代码中使用 boost 吗?

    最佳答案

    智能指针的基本属性

    当您拥有可以分配每个智能指针的属性时,这很容易。有三个重要的属性。

  • 根本没有所有权
  • 所有权转让
  • 所有权份额

  • 第一个意思是智能指针不能删除对象,因为它不拥有它。第二种意味着只有一个智能指针可以同时指向同一个对象。例如,如果要从函数返回智能指针,则所有权将转移到返回的智能指针。

    第三个意思是多个智能指针可以同时指向同一个对象。这也适用于原始指针,但是原始指针缺少一个重要的特性:它们没有定义它们是否拥有。如果每个所有者都放弃该对象,则所有权共享智能指针将删除该对象。这种行为恰好经常需要,因此共享拥有智能指针被广泛传播。

    一些拥有智能指针既不支持第二个也不支持第三个。因此它们不能从函数返回或传递到其他地方。哪个最适合RAII目的是将智能指针保留在本地并刚刚创建,以便在超出范围后释放对象。

    所有权共享可以通过复制构造函数来实现。这自然会复制一个智能指针,并且拷贝和原始指针都将引用同一个对象。所有权的转移目前无法在 C++ 中真正实现,因为没有办法将某些东西从一个对象转移到该语言支持的另一个对象:如果您尝试从函数返回一个对象,则发生的情况是该对象被复制。因此,实现所有权转移的智能指针必须使用复制构造函数来实现所有权转移。然而,这反过来又破坏了它在容器中的使用,因为需求声明了容器元素的复制构造函数的某些行为,这与这些智能指针的这种所谓的“移动构造函数”行为不兼容。

    C++1x 通过引入所谓的“移动构造函数”和“移动赋值运算符”为所有权转移提供了 native 支持。它还带有这样一个名为unique_ptr的所有权转让智能指针。 .

    分类智能指针
    scoped_ptr是一个既不可转让也不可共享的智能指针。如果您需要在本地分配内存,则它仅可用,但请确保在超出范围时再次释放它。但如果您愿意,它仍然可以与另一个 scoped_ptr 交换。
    shared_ptr是一个共享所有权的智能指针(上面的第三种)。它是引用计数的,因此它可以看到它的最后一个拷贝何时超出范围,然后释放所管理的对象。
    weak_ptr是一个非拥有的智能指针。它用于在不添加引用计数的情况下引用托管对象(由 shared_ptr 管理)。通常,您需要从 shared_ptr 中获取原始指针并将其复制。但这并不安全,因为您无法检查对象何时被实际删除。因此,weak_ptr 通过引用由 shared_ptr 管理的对象来提供方法。如果您需要访问该对象,您可以锁定它的管理(以避免在另一个线程中使用该对象时 shared_ptr 释放它)然后使用它。如果weak_ptr 指向一个已经被删除的对象,它会通过抛出异常来通知你。当你有一个循环引用时,使用 weak_ptr 是最有益的:引用计数不能轻易应对这种情况。
    intrusive_ptr就像一个 shared_ptr 但它不会将引用计数保留在 shared_ptr 中,而是将计数的递增/递减留给一些需要由管理的对象定义的辅助函数。这样做的好处是可以将已经被引用的对象(其引用计数由外部引用计数机制递增)填充到 intrusive_ptr 中 - 因为引用计数不再是智能指针的内部,但智能指针使用现有的引用计数机制。
    unique_ptr是所有权的转移指针。你不能复制它,但你可以使用 C++1x 的移动构造函数移动它:
    unique_ptr<type> p(new type);
    unique_ptr<type> q(p); // not legal!
    unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object
    unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!
    

    这是 std::auto_ptr 遵循的语义,但由于缺少对移动的原生支持,它无法毫无缺陷地提供它们。 unique_ptr 将自动从临时的其他 unique_ptr 中窃取资源,这是移动语义的关键特征之一。 auto_ptr 将在下一个 C++ 标准版本中被弃用,以支持 unique_ptr。 C++1x 还允许填充只能移动但不能复制到容器中的对象。因此,您可以将 unique_ptr 填充到 vector 中。到此为止,请引用 a fine article如果你想阅读更多关于这个。

    关于c++ - 智能指针( boost )解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/569775/

    有关c++ - 智能指针( boost )解释的更多相关文章

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

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

    2. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

      我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

    3. 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.你能做的最好的事情是:

    4. ruby - 如何计算 Liquid 中的变量 +1 - 2

      我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

    5. ruby - 解释为局部变量会覆盖方法名称吗? - 2

      如thisquestion,当在其自己的赋值中使用未定义的局部变量时,它的计算结果为nil。x=x#=>nil但是当局部变量的名称与现有的方法名称冲突时,就比较棘手了。为什么下面的最后一个示例返回nil?{}.instance_eval{a=keys}#=>[]{}.instance_eval{keys=self.keys}#=>[]{}.instance_eval{keys=keys}#=>nil 最佳答案 在Ruby中,因为可以在没有显式接收器和括号的情况下调用方法,所以在局部变量引用和无接收器无参数方法调用之间存在语法歧义:f

    6. 语法类似于 GitHub Flavored Markdown 的 Ruby markdown 解释器? - 2

      我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong

    7. arrays - Ruby 数组 += vs 推送 - 2

      我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

    8. += 的 Ruby 方法 - 2

      有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

    9. ruby 变量作为同一对象(指针?) - 2

      >>a=5=>5>>b=a=>5>>b=4=>4>>a=>5如何将“b”设置为实际的“a”,以便在示例中,变量a也将变为4。谢谢。 最佳答案 classRefdefinitializeval@val=valendattr_accessor:valdefto_s@val.to_sendenda=Ref.new(4)b=aputsa#=>4putsb#=>4a.val=5putsa#=>5putsb#=>5当您执行b=a时,b指向与a相同的对象(它们具有相同的object_id).当你执行a=some_other_thing时,a将指向

    10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

      出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

    随机推荐