为什么std :: shared_ptr< void>工作 [英] Why do std::shared_ptr<void> work

查看:97
本文介绍了为什么std :: shared_ptr< void>工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现一些代码使用std :: shared_ptr在关机时执行任意清理。起初我以为这个代码不可能工作,但后来我尝试以下:

I found some code using std::shared_ptr to perform arbitrary cleanup at shutdown. At first I thought this code could not possibly work, but then I tried the following:

#include <memory>
#include <iostream>
#include <vector>

class test {
public:
  test() {
    std::cout << "Test created" << std::endl;
  }
  ~test() {
    std::cout << "Test destroyed" << std::endl;
  }
};

int main() {
  std::cout << "At begin of main.\ncreating std::vector<std::shared_ptr<void>>" 
            << std::endl;
  std::vector<std::shared_ptr<void>> v;
  {
    std::cout << "Creating test" << std::endl;
    v.push_back( std::shared_ptr<test>( new test() ) );
    std::cout << "Leaving scope" << std::endl;
  }
  std::cout << "Leaving main" << std::endl;
  return 0;
}

此程序提供输出:

At begin of main.
creating std::vector<std::shared_ptr<void>>
Creating test
Test created
Leaving scope
Leaving main
Test destroyed

我有一些想法为什么这可能工作,这与std :: shared_ptrs的内部实现为G ++实现。因为这些对象包含内部指针和计数器从 std :: shared_ptr< test> std :: shared_ptr< void& code>可能不会阻碍析构函数的调用。这个假设是正确的吗?

I have some ideas on why this might work, that have to do with the internals of std::shared_ptrs as implemented for G++. Since these objects wrap the internal pointer together with the counter the cast from std::shared_ptr<test> to std::shared_ptr<void> is probably not hindering the call of the destructor. Is this assumption correct?

当然更重要的问题:这是保证工作的标准,或可能进一步更改std :: shared_ptr ,其他实现实际上打破了这个代码?

And of course the much more important question: Is this guaranteed to work by the standard, or might further changes to the internals of std::shared_ptr, other implementations actually break this code?

推荐答案

诀窍是 std :: shared_ptr 执行类型擦除。基本上,当创建一个新的 shared_ptr 时,它会在内部存储一个 deleter 函数构造函数,但如果不存在默认调用 delete )。当 shared_ptr 被销毁时,它会调用该存储函数并调用 deleter

The trick is that std::shared_ptr performs type erasure. Basically, when a new shared_ptr is created it will store internally a deleter function (which can be given as argument to the constructor but if not present defaults to calling delete). When the shared_ptr is destroyed, it calls that stored function and that will call the deleter.

使用std :: function简化的类型擦除的简单草图,避免所有引用计数和其他问题可以在这里看到:

A simple sketch of the type erasure that is going on simplified with std::function, and avoiding all reference counting and other issues can be seen here:

template <typename T>
void delete_deleter( void * p ) {
   delete static_cast<T*>(p);
}

template <typename T>
class my_unique_ptr {
  std::function< void (void*) > deleter;
  T * p;
  template <typename U>
  my_unique_ptr( U * p, std::function< void(void*) > deleter = &delete_deleter<U> ) 
     : p(p), deleter(deleter) 
  {}
  ~my_unique_ptr() {
     deleter( p );   
  }
};

int main() {
   my_unique_ptr<void> p( new double ); // deleter == &delete_deleter<double>
}
// ~my_unique_ptr calls delete_deleter<double>(p)

当一个 shared_ptr 被复制(或默认构造)从另一个去传递时,所以当你构造一个 shared_ptr< T> shared_ptr< U> 有关什么析构函数调用的信息也在

When a shared_ptr is copied (or default constructed) from another the deleter is passed around, so that when you construct a shared_ptr<T> from a shared_ptr<U> the information on what destructor to call is also passed around in the deleter.

这篇关于为什么std :: shared_ptr&lt; void&gt;工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆