19

http://www.drdobbs.com/cpp/practical-c-error-handling-in-hybrid-env/197003350?pgno=4

この記事では、Herb Sutterが、例外をスローするには、一時として作成されるため、例外のコピーが必要であり、したがってstd::auto_ptr、コピーのオーバーヘッドを回避するためにを使用することを説明しています。C ++ 11で利用可能になっている移動セマンティクスに照らして、これはまだ必要ですか?

4

3 に答える 3

15

確認したところ、標準では許可されています

  • スロー式のオペランドで指定されたオブジェクトの例外オブジェクトへのコピーまたは移動を省略します
  • プログラムの意味を変更しない場合(つまり、再スローして後続のキャッチで突然変更された例外オブジェクトが表示される場合)、例外オブジェクトのコピーまたは移動を例外オブジェクトと同じタイプのcatch句変数に省略します。前のcatchブロックによって変更されました)。

これらの省略は許可されているため、仕様では、最初にコピーのソースを考慮するか、右辺値として移動する必要があります。つまり、可能であれば、それぞれのオブジェクトが移動されるということです。もちろん、コピーと移動の省略は、最初の選択肢として引き続き許可されます。


アップデート

右辺値初期化子としてのcatch句パラメーターの例外オブジェクト初期化子の考慮はおそらく標準から削除されると通知されました(一般に、省略したときにプログラムの動作が変更されていないことをすべての場合に検出できるわけではないため)コピー/移動)なので、これに依存しないことをお勧めします(上記の2番目の箇条書き)。

まだ信頼できるのは、 (上記の最初の箇条書き)のように、ローカル変数を例外オブジェクトに移動することですthrow x;

于 2012-08-25T14:25:03.847 に答える
2

現在、例外オブジェクトからの移動は必須ではありません。

これはC++11の欠陥です。CWG1493を参照してください。

于 2014-04-25T17:03:39.320 に答える
0
  • 式をスローすると、スタックの巻き戻しプロセス中に元のオブジェクトがスコープから外れるため、例外オブジェクトのコピーを常に作成する必要があります。
  • その初期化中に、コピーの省略が予想される場合があります(これを参照)–コピーまたは移動コンストラクター(ターゲットオブジェクトのストレージに直接構築されたオブジェクト)を省略します。
  • ただし、コピーの省略が適用される場合とされない場合でも、適切なコピーコンストラクターを提供するか、C ++標準で義務付けられているコンストラクターを移動する必要があります(15.1を参照)。以下のコンパイルエラーを参照してください。

しかし、最新のC ++は、より多くの機能を提供します。「移動セマンティクスと例外を使用して安全に移動する」

struct demo
{
    demo() = default;
    demo(const demo &) { cout << "Copying\n"; }
    // Exception safe move constructor
    demo(demo &&) noexcept { cout << "Moving\n"; }
private:
    std::vector<int>    m_v;
};
int main()
{
    demo obj1;
    if (noexcept(demo(std::declval<demo>()))){  // if moving safe
        demo obj2(std::move(obj1));             // then move it
    }
    else{
        demo obj2(obj1);                        // otherwise copy it
    }
    demo obj3(std::move_if_noexcept(obj1));     // Alternatively you can do this----------------
    return 0;
}
  • のmoveコンストラクターが存在するnoexcept(T(std::declval<T>()))かどうかを確認するために使用できます。これは、 (を使用して)の別のインスタンスを移動することによってのインスタンスを作成するかどうかを決定するためのものです。TnoexceptTTstd::move
  • または、演算子std::move_if_noexceptを使用noexceptして右辺値または左辺値にキャストするを使用することもできます。このようなチェックは、std::vectorおよび他のコンテナで使用されます。
  • これは、失いたくない重要なデータを処理しているときに役立ちます。たとえば、サーバーから受信した重要なデータがあり、処理中にデータを失いたくない場合があります。このような場合、std::move_if_noexceptmoveコンストラクターが例外セーフである場合にのみ、重要なデータの所有権を移動するwhichを使用する必要があります。

From:C++での例外処理の7つのベストプラクティス

于 2019-11-09T08:07:45.113 に答える