2012-01-10 15 views
3

リファレンスカウントのために、以下のサンプルコードのようにstd :: tr1 :: shared_ptrを使用するのは安全で正しいですか? (これは、単に特定のサンプルで、クラスではなくFILE *の)*(無効何かを含めることができます)リファレンスカウントの内部メカニズムとしてstd :: tr1 :: shared_ptrを使用

class File 
{ 
public: 
    File(const char* path, const char* mode) : 
     _refcount(new int(0)) 
    { 
     this->_file = fopen(path, mode); 
    } 

    ~File() 
    { 
     if (this->_refcount.unique()) 
     { 
      if (this->_file != NULL) 
      { 
       fclose(this->_file); 
      } 
     } 
    } 

    int write(void* buff, size_t size) 
    { 
     fwrite(buff, size, 1, this->_file); 
    } 

private: 
    FILE* _file; 
    std::tr1::shared_ptr<int> _refcount; 
}; 
+1

どのような意味で安全ですか?メモリは安全ですか?スレッドセーフ? – kennytm

+0

@KennyTMはい、メモリ安全でスレッドセーフで、他の観点から見てください。 (私はそれがスレッドセーフではないと思う、多分あなたはそれが固定する方法を説明することができます) –

+0

私はそれがスレッドセーフではないと言っていない;)しかし、私はジェームズのソリューションのように明示的なref-カウンタ。 – kennytm

答えて

9

カスタム削除手段とshared_ptr<FILE>を使用して代わりに考えてみましょう:

struct fclose_deleter 
{ 
    void operator()(FILE* f) 
    { 
     if (f) 
     { 
      std::fclose(f); 
     } 
    } 
}; 

その後、あなたのFileクラスははるかに簡単です(そして修正子):

class File 
{ 
public: 
    File(const char* path, const char* mode) 
     : _file(std::fopen(path, mode), fclose_deleter()) 
    { 
    } 

    int write(void const* buff, size_t size) 
    { 
     // You'll want to verify that _file.get() is valid, or you'll want to 
     // throw in the constructor if the call to 'std::fopen()' fails. 
     std::fwrite(buff, size, 1, _file.get()); 
    } 

private: 
    std::tr1::shared_ptr<FILE> _file; 
}; 
+0

クラスには任意のデータ(void *)を含めることができます。ファイルは単なる例に過ぎません –

+3

このテクニックは、クリーンアップを必要とする参照カウントオブジェクトに適用されます。 –

+1

これと他の興味深い 'shared_ptr'テクニックはここにあります:http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/sp_techniques.html :) –

関連する問題