【问题标题】:Explicitly deleting a shared_ptr显式删除 shared_ptr
【发布时间】:2012-09-01 13:32:28
【问题描述】:

这里有一个简单的问题:您是否可以自己显式删除boost::shared_ptr?你应该过吗?

澄清一下,我不是说删除shared_ptr 持有的指针。我的意思是实际的shared_ptr 本身。我知道大多数人建议不要这样做,所以我只是想知道是否可以明确地这样做。

【问题讨论】:

  • 当然可以删除(动态分配的)shared_ptr;删除它的内容是一个完全不同的问题;-)
  • 我想你在找weak_ptr
  • 动态分配shared_ptr 违背了使用shared_ptr 的目的。
  • 你到底为什么要在堆上分配一个shared_ptr
  • 您的问题与“如果我用 new 分配一个对象,我可以显式删除它吗?”没有什么不同。 ……答案当然是肯定的——你可以而且你应该这样做。对象的类型无关紧要。

标签: c++ boost shared-ptr boost-smart-ptr


【解决方案1】:

你的问题不清楚。如果您已经动态分配了shared_ptr,那么您当然可以随时使用delete

但是,如果您要问是否允许删除 shared_ptr 管理的任何对象,那么答案是……这取决于。如果shared_ptr::unique 返回true,那么调用shared_ptr::reset 将删除托管对象。但是,如果 shared_ptr::unique 返回 false,则意味着有多个 shared_ptrs 共享该对象的所有权。在这种情况下,对reset 的调用只会导致引用计数减1,当最后一个管理该对象的shared_ptr 超出范围或本身是reset 时,将实际删除该对象。

编辑:
编辑后,您似乎在询问是否要删除动态分配的shared_ptr。像这样的:

auto sp = new boost::shared_ptr<int>( new int(42) );

// do something with sp

delete sp;

这是允许的,并且会按预期工作,尽管这将是一个不寻常的用例。唯一需要注意的是,如果在分配和删除sp 之间创建另一个共享对象所有权的shared_ptr,删除sp 不会导致删除对象,这只会在引用计数时发生对象变为 0。

【讨论】:

    【解决方案2】:

    [编辑:你可以delete a shared_ptr 当且仅当它是用new 创建的,与任何其他类型相同。我想不出你为什么要用new 创建shared_ptr,但没有什么能阻止你。]

    好吧,你可以delete ptr.get();

    这样做几乎不可避免地会导致未定义的行为,或者当其他共享所有者使用他们的shared_ptr 访问现在删除的对象,或者对象的最后一个shared_ptr 被销毁,并且对象再次被删除。

    所以不,你不应该。

    shared_ptr 的目的是管理一个没有任何“人”有权或有责任删除的对象,因为可能有其他人共享所有权。所以你也不应该想要。

    【讨论】:

      【解决方案3】:

      你不能强制它的引用计数为零,不。

      想想它需要什么才能发挥作用。您需要去每个使用 shared_ptr 的地方并清除它。

      如果你确实强制删除共享指针并将其设置为 NULL,它就像一个weak_ptr。但是,代码中使用 shared_ptr 的所有这些地方都没有为此做好准备,并且期望持有一个有效的指针。他们没有理由检查 NULL,因此这些代码会崩溃。

      【讨论】:

        【解决方案4】:

        如果要模拟计数递减,可以像这样在堆上手动进行:

        int main(void) {
            std::shared_ptr<std::string>* sp = new std::shared_ptr<std::string>(std::make_shared<std::string>(std::string("test")));
            std::shared_ptr<std::string>* sp2 = new std::shared_ptr<std::string>(*sp);
            delete sp;
        
            std::cout << *(*sp2) << std::endl;    // test
            return 0;
        }
        

        或者像这样在堆栈上使用std::shared_ptr::reset()

        int main(void) {
            std::shared_ptr<std::string> p = std::make_shared<std::string>(std::string("test"));
            std::shared_ptr<std::string> p2 = p;
            p.reset();
        
            std::cout << *p2 << std::endl;    // test
            return 0;
        } 
        

        但这没什么用。

        【讨论】:

          【解决方案5】:

          在某些(非常?)极少数情况下,显式删除会派上用场。

          除了显式删除之外,有时您必须在“删除”共享指针时显式销毁它!

          当与 C 代码交互时,事情会变得很奇怪,将 shared_ptr 作为不透明值传递。

          例如,我有以下用于将对象传入和传出用 C 编写的 Lua 脚本语言(www.lua.org)

          static void push( lua_State *L, std::shared_ptr<T> sp )
          {
              if( sp == nullptr ) {
                  lua_pushnil( L );
                  return;
              }
          
              // This is basically malloc from C++ point of view.
              void *ud = lua_newuserdata( L, sizeof(std::shared_ptr<T>));
          
              // Copy constructor, bumps ref count.
              new(ud) std::shared_ptr<T>( sp );
          
              luaL_setmetatable( L, B::class_name );
          }
          

          所以这是一些 malloc 内存中的 shared_ptr。反过来是这样...(在 Lua 垃圾收集对象并“释放它”之前调用设置)。

          static int destroy( lua_State *L )
          {
              // Grab opaque pointer
              void* ud = luaL_checkudata( L, 1, B::class_name );
          
              std::shared_ptr<T> *sp = static_cast<std::shared_ptr<T>*>(ud);
          
              // Explicitly called, as this was 'placement new'd
              // Decrements the ref count
              sp->~shared_ptr();
          
              return 0;
          }
          

          【讨论】:

            猜你喜欢
            • 2013-09-24
            • 1970-01-01
            • 2021-11-13
            • 2014-09-08
            • 2016-01-03
            • 2020-06-19
            • 1970-01-01
            • 1970-01-01
            • 2010-10-11
            相关资源
            最近更新 更多