質問

私はスコープガード(ジェネリックについての記事を読んだ:変更ウェイあなたの書き込み例外セーフコード - 永遠こちら)DDJで、私は彼らの一般的な使用方法を理解する

しかし、一般的な使用は、例えば、特定の動作のためにスタック上の特定のスタックガードをインスタンス化することである:

{
    FILE* topSecret = fopen("cia.txt");
    ON_BLOCK_EXIT(std::fclose, topSecret);
    ... use topSecret ...
} // topSecret automagically closed

が、私は、実行時にスケジュールのクリーンアップ操作する場合はどのような、例えば私はループを持っているときます:

{
   vector<FILE*> topSecretFiles;
   for (int i=0; i<numberOfFiles; ++i)
   {
      char filename[256];
      sprintf(filename, "cia%d.txt", i);
      FILE* topSecret = fopen(filename);
      topSecretFiles.push_back(topSecret);
      ON_BLOCK_EXIT(std::fclose, topSecret); // no good
   }
}

はもちろん、上記の例ではtopSecretのためのの範囲と共に閉鎖されるので、動作しません。私は同じように簡単にランタイムの時の私は必要であると判断するクリーンアップ操作をキューすることができますスコープガードパターンをしたいと思います。利用できるこのようなものはありますか?

元のオブジェクト(私が押してるもの)プロセスで却下されるだろう原因

私は、標準キューにスコープガードオブジェクトをプッシュすることはできません。どのようにヒープ割り当てられたスタックガードを押し、デストラクタで、そのメンバーを削除したキューを使用してはどうですか?誰もがより巧妙なアプローチを持っていますか?

役に立ちましたか?

解決

あなたがそれが何であるかのためRAIIを感謝していないようです。これらのスコープガードは、ローカル(「スコープ」)もののための機会にいいですが、あなたはRAIIが本当に行うことになっているものの賛成でそれらを回避しようとしてください:オブジェクト内のリソースをカプセル化します。型FILE *その時は本当にちょうど良いではありません。

ここでの代替があります:

void foo() {
    typedef std::tr1::shared_ptr<FILE> file_sptr;
    vector<file_sptr> bar;
    for (...) {
        file_sptr fsp ( std::fopen(...), std::fclose );
        bar.push_back(fsp);
    }
}

それともます:

void foo() {
    typedef std::tr1::shared_ptr<std::fstream> stream_sptr;
    vector<stream_sptr> bar;
    for (...) {
        file_sptr fsp ( new std::fstream(...) );
        bar.push_back(fsp);
    }
}

または "C ++ 0xの"(次期C ++標準)で

void foo() {
    vector<std::fstream> bar;
    for (...) {
        // streams will become "movable"
        bar.push_back( std::fstream(...) );
    }
}

編集:私はC ++ 0xの可動タイプのような多くのようにあなたがそれに興味を示したが、以来:ここでは、FILEとの組み合わせでunique_ptrを使用することができます方法です* のいずれかの参照カウントオーバーヘッドなし

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

typedef std::unique_ptr<FILE,file_closer> file_handle;

file_handle source() {
    file_handle fh ( std::fopen(...) );
    return fh;
}

int sink(file_handle fh) {
    return std::fgetc( fh.get() );
}

int main() {
    return sink( source() );
}

(未試験)

効率的な可動値型の

チェックアウトしてください Daveのブログ

他のヒント

許は、DDJスコープガードアウトターンはないC ++ 0xの意味で、「可動」であるが、同じ意味でのauto_ptrは移動可能であること:コピーctorの間に、新しいガード「却下」の古いガード(auto_ptrはのコピーctorのは、古いものののauto_ptrは::リリースを呼び出すようにの)ます。

だから私は単にqueue<ScopeGuard>を保つことができ、それがうまくいくます:

queue<ScopeGuard> scopeGuards;

// ...

for (...)
{
   // the temporary scopeguard is being neutralized when copied into the queue,
   // so it won't cause a double call of cleanupFunc
   scopeGuards.push_back(MakeScopeGuard(cleanupFunc, arg1));
   // ...
}
ところで、上記の回答をありがとうございました。これは、さまざまな方法で私に有益と教育だった。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top