譲std::shared_ptrがダイナミックタイプポインタになる


作成者:[email protected] 
      
c++11に導入されたshared_ptrはスレッドセキュリティ共有ポインタ技術をカプセル化することができ,開発者に大きな便利さをもたらした.しかし、アメリカで足りないのはshared_ptrはテンプレートに基づいており、以下のように宣言されています.
   template<class T>   class shared_ptr;
そして、存在しない"shared_ptr"のような汎用タイプです.したがって、原則としてshared_ptrごとに1つのポインタタイプしか管理できません.
強制型変換がこの問題を解決できると考える人もいるかもしれません.たとえば、MyClassクラスのポインタがあり、shared_に次のように配置できます.ptrで:
    MyClass* p = new MyClass();
    std::shared_ptr<char> spMy(reinterpret_cast<char*>(p));

しかし、spMyが破棄された場合、MyClassの構造関数が呼び出されていない可能性が高いことがわかります.なぜなら、c++はshared_を通過するptrはMyClassではなくcharの構造関数を探しています.
この問題を解決するためにsharedを利用することができます.ptrコンストラクション関数のDeleterパラメータ:
    template< class T, class Deleter >
    shared_ptr( T* ptr, Deleter d );

いくつかの補助施設を加えるとshared_ptrは「ダイナミックタイプ」ポインタをサポートします.私たちのDeleterは以下の通りです.
    template<class T>
    struct MyDeleter
    {
        inline void operator()(void* pData)
        {
            delete static_cast<T*>(pData);
        }
    };

    template<class T>
    struct MyDeleter<T[]>
    {
        inline void operator()(void* pData)
        {
            delete[] static_cast<T*>(pData);
        }
    };

テスト例は次のとおりです.
using namespace std;

class MyClass
{
public:
    ~MyClass()
    {
        cout << "~MyClass() is called." << endl;
    }
};

int main()
{
	{
		cout << "test shared_ptr of MyClass" << endl;
		MyClass* p = new MyClass();
		std::shared_ptr<char> spSingle(reinterpret_cast<char*>(p), MyDeleter<MyClass>());
	}
	
	{
		cout << "test shared_ptr of MyClass array" << endl;		               
		MyClass* p = new MyClass[10];
		std::shared_ptr<char> spArray(reinterpret_cast<char*>(p), MyDeleter<MyClass[]>());
	}
	return 0;
}

カスタムタイプでもカスタムタイプ配列でもshared_ptrは正しく管理されています.もちろん、プログラムをより完璧にするためにshared_ptrはカプセル化され,必要なインタフェースのみが露出し,具体的な方法はここでは後述しない.本文がレンガを投げて玉を引く役割を果たすことを望みます:)