5

RAII オブジェクトを構築するとします。そのオブジェクトは構築に失敗する可能性があります。どうすればこれを処理できますか?

try {
    std::vector<int> v(LOTS);
    // try scope ends here because that's what the catch is for
} catch( const std::bad_alloc& ) {
    // ...
}
// v? what v?

確かに、のデフォルトのコンストラクターはstd::vectorスローされず、それが役立ちますが、これは一般的なケースではありません。コンストラクターはスローする可能性があります。リソース取得の失敗を処理したい場合、それがスローされない場合でも続行できるようにするにはどうすればよいですか?

編集:明確にするために、私の問題は、リソースの取得に失敗した場合、もう一度やり直したくなるかもしれないということです。代替リソースを取得してみることができるかもしれません。

4

4 に答える 4

7

「進む」が何を意味するかによります。リソースを必要とする操作はすべて失敗します。それが「必要」の意味です。したがって、エラーの後で続行したい場合は、次のようなコードを書くことになるかもしれません:

void something_using_RAII(thingummy &t) {
    vector<int> v(t.size_required);
    // do something using v
}

...

for each thingummy {
    try {
         something_using_RAII(this_thingummy);
    } catch(const std::bad_alloc &) {
         std::cerr << "can't manage that one, sorry\n";
    }
}

そのため、例外を処理する価値がある場合にのみ例外をキャッチする必要があります (この場合は、失敗を報告して次の作業に進みます)。

失敗時に再試行したいが、コンストラクターが失敗した場合にのみ、他の何かが失敗した場合ではない場合:

while(not bored of trying) {
    bool constructor_failed = true;
    try {
        vector<int> v(LOTS);
        constructor_failed = false;
        // use v
    } catch(...) {
        if (!constructor_failed) throw;
    }
}

これは多かれ少なかれどのように機能するかstd::new_handlerです - ハンドラーは同様のループの catch 句で呼び出されますが、フラグは必要ありません。

失敗時に別のリソースを試したい場合:

try {
    vector<int> v(LOTS);
    // use v
} catch(...) try {
    otherthing<int> w(LOTS);
    // use w
} catch(...) {
    // failed
}

「v を使用」と「w を使用」が基本的に同じコードである場合は、関数にリファクタリングし、両方の場所から呼び出します。この時点で、関数はかなり多くのことを行っています。

于 2010-10-31T15:13:05.757 に答える
7

RAII コンストラクターがスローすると、スローポイントより前に RAII オブジェクトにバインドされたすべてのリソースが適切にクリーンアップされます。C++ の規則は、それを保証するように賢明に設計されています。

vが原因で構築がスローされた場合、ブロック内でbad_alloc以前に作成された RAII オブジェクトは適切にクリーンアップされます。vtry

したがって、結果として RAII を使用する場合は、RAII オブジェクトがクリーンアップを処理するため、マニュアルなどtryは必要ありません。何らかの理由でそれcatch必要な場合は、上記の場合、次のように swap を使用できます。

std::vector<int> v;
try {
    std::vector<int> vtry(LOTS);
    v.swap(vtry); // no-throw
} catch( const std::bad_alloc& ) {
    // ...
}
// v!
于 2010-10-31T15:12:39.530 に答える
2

作成できない場合v、使用しようとするすべてのコードをv実行できません。catchコードが使用するコードの後に​​、vがない場合に実行を継続するのが適切な場所に移動しvます。

于 2010-10-31T15:14:09.600 に答える
0

v を使用するすべてのコードは、try ブロックにある必要があります。問題が、例外をスローしたコードを絞り込む方法である場合は、次のように、ある種のフラグを使用して、try ブロックのどこにいるかを示すことができます。

string flag;
try
{
    flag = "creating vector<int> v";
    std::vector<int> v(LOTS);

    flag = "performing blaggity bloop";
    blaggity_bloop();

    flag = "doing some other stuff";
    some_other_stuff();
}
catch( const std::bad_alloc& )
{
    cerr << "Bad allocation while " << flag << endl;
}
于 2010-10-31T16:13:24.477 に答える